8142968: Module System implementation

Initial integration of JEP 200, JEP 260, JEP 261, and JEP 282

Co-authored-by: Alex Buckley <alex.buckley@oracle.com>
Co-authored-by: Jonathan Gibbons <jonathan.gibbons@oracle.com>
Co-authored-by: Karen Kinnear <karen.kinnear@oracle.com>
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Co-authored-by: Mark Reinhold <mark.reinhold@oracle.com>
Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com>
Co-authored-by: Vicente Romero <vicente.romero@oracle.com>
Co-authored-by: Andreas Lundblad <andreas.lundblad@oracle.com>
Co-authored-by: Andrey Nazarov <andrey.x.nazarov@oracle.com>
Co-authored-by: Chris Hegarty <chris.hegarty@oracle.com>
Co-authored-by: Erik Joelsson <erik.joelsson@oracle.com>
Co-authored-by: Kumar Srinivasan <kumar.x.srinivasan@oracle.com>
Co-authored-by: Sundararajan Athijegannathan <sundararajan.athijegannathan@oracle.com>
Reviewed-by: jjg, jlahoda, vromero, mcimadamore, bpatel, ksrini, darcy, anazarov, dfuchs
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java
index a57f7b8..3c00e68 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -105,8 +105,8 @@
      * java.util.Set<E>} is {@code "Set"}.
      *
      * If this element represents an unnamed {@linkplain
-     * PackageElement#getSimpleName package}, an empty name is
-     * returned.
+     * PackageElement#getSimpleName package} or unnamed {@linkplain
+     * ModuleElement#getSimpleName module}, an empty name is returned.
      *
      * If it represents a {@linkplain ExecutableElement#getSimpleName
      * constructor}, the name "{@code <init>}" is returned.  If it
@@ -122,6 +122,7 @@
      * @see ExecutableElement#getSimpleName
      * @see TypeElement#getSimpleName
      * @see VariableElement#getSimpleName
+     * @see ModuleElement#getSimpleName
      */
     Name getSimpleName();
 
@@ -137,7 +138,7 @@
      * top-level type}, its package is returned.
      *
      * <li> If this is a {@linkplain
-     * PackageElement#getEnclosingElement package}, {@code null} is
+     * PackageElement#getEnclosingElement package}, its module is
      * returned.
      *
      * <li> If this is a {@linkplain
@@ -150,6 +151,9 @@
      * parameter}, {@linkplain ExecutableElement the executable
      * element} which declares the parameter is returned.
      *
+     * <li> If this is a {@linkplain ModuleElement#getEnclosingElement
+     * module}, {@code null} is returned.
+     *
      * </ul>
      *
      * @return the enclosing element, or {@code null} if there is none
@@ -169,6 +173,9 @@
      * encloses the top-level classes and interfaces within it, but is
      * not considered to enclose subpackages.
      *
+     * A {@linkplain ModuleElement#getEnclosedElements module}
+     * encloses packages within it.
+     *
      * Other kinds of elements are not currently considered to enclose
      * any elements; however, that may change as this API or the
      * programming language evolves.
@@ -177,8 +184,9 @@
      * methods in {@link ElementFilter}.
      *
      * @return the enclosed elements, or an empty list if none
-     * @see PackageElement#getEnclosedElements
      * @see TypeElement#getEnclosedElements
+     * @see PackageElement#getEnclosedElements
+     * @see ModuleElement#getEnclosedElements
      * @see Elements#getAllMembers
      * @jls 8.8.9 Default Constructor
      * @jls 8.9 Enums
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java
index 2561cb8..e98d454 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -94,7 +94,13 @@
      * A resource variable.
      * @since 1.7
      */
-    RESOURCE_VARIABLE;
+     RESOURCE_VARIABLE,
+
+    /**
+     * A module.
+     * @since 9
+     */
+     MODULE;
 
 
     /**
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java
index e065551..a06a5c2 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -143,4 +143,13 @@
      *  a visitor implementation may optionally throw this exception
      */
     R visitUnknown(Element e, P p);
+
+    /**
+     * Visits a module element.
+     * @param e  the element to visit
+     * @param p  a visitor-specified parameter
+     * @return a visitor-specified result
+     * @since 9
+     */
+    R visitModule(ModuleElement e, P p);
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java
new file mode 100644
index 0000000..306bf82
--- /dev/null
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.lang.model.element;
+
+import java.util.List;
+
+/**
+ * Represents a module program element.  Provides access to information
+ * about the module and its members.
+ *
+ * @see javax.lang.model.util.Elements#getModuleOf
+ * @since 9
+ */  // TODO: add @jls to module section
+public interface ModuleElement extends Element, QualifiedNameable {
+
+    /**
+     * Returns the fully qualified name of this module.
+     *
+     * @return the qualified name of this module, or an
+     * empty name if this is an unnamed module
+     */
+    @Override
+    Name getQualifiedName();
+
+    /**
+     * Returns the simple name of this module.  For an unnamed
+     * module, an empty name is returned.
+     *
+     * @return the simple name of this module or an empty name if
+     * this is an unnamed module
+     */
+    @Override
+    Name getSimpleName();
+
+    /**
+     * Returns the packages within this module.
+     * @return the packages within this module
+     */
+    @Override
+    List<? extends Element> getEnclosedElements();
+
+    /**
+     * Returns {@code true} if this is an unnamed module and {@code
+     * false} otherwise.
+     *
+     * @return {@code true} if this is an unnamed module and {@code
+     * false} otherwise
+     */ // TODO: add @jls to unnamed module section
+    boolean isUnnamed();
+
+    /**
+     * Returns {@code null} since a module is not enclosed by another
+     * element.
+     *
+     * @return {@code null}
+     */
+    @Override
+    Element getEnclosingElement();
+
+    /**
+     * Returns the directives contained in the declaration of this module.
+     * @return  the directives in the declaration of this module
+     */
+    List<? extends Directive> getDirectives();
+
+    /**
+     * The {@code kind} of a directive.
+     *
+     * <p>Note that it is possible additional directive kinds will be added
+     * to accommodate new, currently unknown, language structures added to
+     * future versions of the Java&trade; programming language.
+     *
+     * @since 9
+     */
+    enum DirectiveKind {
+        /** A "requires [public] module-name" directive. */
+        REQUIRES,
+        /** An "exports package-name [to module-name-list]" directive. */
+        EXPORTS,
+        /** A "uses service-name" directive. */
+        USES,
+        /** A "provides service-name with implementation-name" directive. */
+        PROVIDES
+    };
+
+    /**
+     * Represents a "module statement" within the declaration of this module.
+     *
+     * @since 9
+     *
+     */ // TODO: add jls to Module Statement
+    interface Directive {
+        /**
+         * Returns the {@code kind} of this directive.
+         *
+         * @return the kind of this directive
+         */
+        DirectiveKind getKind();
+    }
+
+    /**
+     * A dependency of a module.
+     * @since 9
+     */
+    interface RequiresDirective extends Directive {
+        /**
+         * Returns whether or not this is a public dependency.
+         * @return whether or not this is a public dependency
+         */
+        boolean isPublic();
+
+        /**
+         * Returns the module that is required
+         * @return the module that is required
+         */
+        ModuleElement getDependency();
+    }
+
+    /**
+     * An exported package of a module.
+     * @since 9
+     */
+    interface ExportsDirective extends Directive {
+        /**
+         * Returns the package being exported.
+         * @return the package being exported
+         */
+        PackageElement getPackage();
+
+        /**
+         * Returns the specific modules to which the package is being exported,
+         * or null, if the package is exported to all modules which
+         * have readability to this module.
+         * @return the specific modules to which the package is being exported
+         */
+        List<? extends ModuleElement> getTargetModules();
+    }
+
+    /**
+     * An implementation of a service provided by a module.
+     * @since 9
+     */
+    interface ProvidesDirective extends Directive {
+        /**
+         * Returns the service being provided.
+         * @return the service being provided
+         */
+        TypeElement getService();
+
+        /**
+         * Returns the implementation of the service being provided.
+         * @return the implementation of the service being provided
+         */
+        TypeElement getImplementation();
+    }
+
+    /**
+     * A reference to a service used by a module.
+     * @since 9
+     */
+    interface UsesDirective extends Directive {
+        /**
+         * Returns the service that is used.
+         * @return the service that is used
+         */
+        TypeElement getService();
+    }
+}
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
index 1aafd34..f319d31 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -72,20 +72,19 @@
     List<? extends Element> getEnclosedElements();
 
     /**
-     * Returns {@code true} is this is an unnamed package and {@code
+     * Returns {@code true} if this is an unnamed package and {@code
      * false} otherwise.
      *
-     * @return {@code true} is this is an unnamed package and {@code
+     * @return {@code true} if this is an unnamed package and {@code
      * false} otherwise
      * @jls 7.4.2 Unnamed Packages
      */
     boolean isUnnamed();
 
     /**
-     * Returns {@code null} since a package is not enclosed by another
-     * element.
+     * Returns the enclosing module.
      *
-     * @return {@code null}
+     * @return the enclosing module
      */
     @Override
     Element getEnclosingElement();
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java b/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java
index cd974ce..b0a1b62 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,7 +151,14 @@
       *
       * @since 1.8
       */
-    INTERSECTION;
+    INTERSECTION,
+
+    /**
+     * A pseudo-type corresponding to a module element.
+     * @see NoType
+     * @since 9
+     */
+    MODULE;
 
     /**
      * Returns {@code true} if this kind corresponds to a primitive
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java
index b9ea796..54cd3a0 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -132,4 +132,19 @@
     public R visitUnknown(Element e, P p) {
         throw new UnknownElementException(e, p);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by calling {@code
+     * visitUnknown}.
+
+     * @param e  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     *
+     * @since 9
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return visitUnknown(e, p);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java
index c239303..d313514 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -27,6 +27,7 @@
 
 import javax.annotation.processing.SupportedSourceVersion;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
 import static javax.lang.model.SourceVersion.*;
 
 
@@ -71,4 +72,15 @@
     protected AbstractElementVisitor9(){
         super();
     }
+
+    /**
+     * Visits a {@code ModuleElement} in a manner defined by a
+     * subclass.
+     *
+     * @param t  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of the visit as defined by a subclass
+     */
+    @Override
+    public abstract R visitModule(ModuleElement t, P p);
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java
index c4c23fe..e5dbf49 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -33,6 +33,12 @@
 import java.util.LinkedHashSet;
 
 import javax.lang.model.element.*;
+import javax.lang.model.element.ModuleElement.Directive;
+import javax.lang.model.element.ModuleElement.DirectiveKind;
+import javax.lang.model.element.ModuleElement.ExportsDirective;
+import javax.lang.model.element.ModuleElement.ProvidesDirective;
+import javax.lang.model.element.ModuleElement.RequiresDirective;
+import javax.lang.model.element.ModuleElement.UsesDirective;
 
 
 /**
@@ -78,6 +84,9 @@
     private static final Set<ElementKind> PACKAGE_KIND =
         Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE));
 
+    private static final Set<ElementKind> MODULE_KIND =
+        Collections.unmodifiableSet(EnumSet.of(ElementKind.MODULE));
+
     private static final Set<ElementKind> TYPE_KINDS =
         Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
                                                ElementKind.ENUM,
@@ -183,6 +192,28 @@
         return setFilter(elements, PACKAGE_KIND, PackageElement.class);
     }
 
+    /**
+     * Returns a list of modules in {@code elements}.
+     * @return a list of modules in {@code elements}
+     * @param elements the elements to filter
+     * @since 9
+     */
+    public static List<ModuleElement>
+            modulesIn(Iterable<? extends Element> elements) {
+        return listFilter(elements, MODULE_KIND, ModuleElement.class);
+    }
+
+    /**
+     * Returns a set of modules in {@code elements}.
+     * @return a set of modules in {@code elements}
+     * @param elements the elements to filter
+     * @since 9
+     */
+    public static Set<ModuleElement>
+            modulesIn(Set<? extends Element> elements) {
+        return setFilter(elements, MODULE_KIND, ModuleElement.class);
+    }
+
     // Assumes targetKinds and E are sensible.
     private static <E extends Element> List<E> listFilter(Iterable<? extends Element> elements,
                                                           Set<ElementKind> targetKinds,
@@ -207,4 +238,62 @@
         }
         return set;
     }
+
+
+
+    /**
+     * Returns a list of export directives in {@code directives}.
+     * @return a list of export directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<ExportsDirective>
+            exportsIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.EXPORTS, ExportsDirective.class);
+    }
+
+    /**
+     * Returns a list of provides directives in {@code directives}.
+     * @return a list of provides directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<ProvidesDirective>
+            providesIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.PROVIDES, ProvidesDirective.class);
+    }
+
+    /**
+     * Returns a list of requires directives in {@code directives}.
+     * @return a list of requires directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<RequiresDirective>
+            requiresIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.REQUIRES, RequiresDirective.class);
+    }
+
+    /**
+     * Returns a list of uses directives in {@code directives}.
+     * @return a list of uses directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<UsesDirective>
+            usesIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.USES, UsesDirective.class);
+    }
+
+    // Assumes directiveKind and D are sensible.
+    private static <D extends Directive> List<D> listFilter(Iterable<? extends Directive> directives,
+                                                          DirectiveKind directiveKind,
+                                                          Class<D> clazz) {
+        List<D> list = new ArrayList<>();
+        for (Directive d : directives) {
+            if (d.getKind() == directiveKind)
+                list.add(clazz.cast(d));
+        }
+        return list;
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java
index a0e51e2..eb1a303 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -95,4 +95,17 @@
     protected ElementKindVisitor9(R defaultValue) {
         super(defaultValue);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by calling {@code
+     * defaultAction}.
+     *
+     * @param e the element to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of {@code defaultAction}
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return defaultAction(e, p);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java
index b6f8810..c7419c8 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -108,4 +108,17 @@
     protected ElementScanner9(R defaultValue){
         super(defaultValue);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by scanning the enclosed
+     * elements.
+     *
+     * @param e the element to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of the scan
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return scan(e.getEnclosedElements(), p); // TODO: Hmmm, this might not be right
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
index bc4eb28..9c3801d 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -30,7 +30,6 @@
 import java.util.Map;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 
 /**
@@ -64,6 +63,15 @@
     TypeElement getTypeElement(CharSequence name);
 
     /**
+     * Returns a module element given its fully qualified name.
+     *
+     * @param name  the name
+     * @return the named module element, or {@code null} if it cannot be found
+     * @since 9
+     */
+    ModuleElement getModuleElement(CharSequence name);
+
+    /**
      * Returns the values of an annotation's elements, including defaults.
      *
      * @see AnnotationMirror#getElementValues()
@@ -129,6 +137,16 @@
     PackageElement getPackageOf(Element type);
 
     /**
+     * Returns the module of an element.  The module of a module is
+     * itself.
+     *
+     * @param type the element being examined
+     * @return the module of an element
+     * @since 9
+     */
+    ModuleElement getModuleOf(Element type);
+
+    /**
      * Returns all members of a type element, whether inherited or
      * declared directly.  For a class the result also includes its
      * constructors, but not local or anonymous classes.
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java
index fae29ca..3b9f3f0 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -27,6 +27,7 @@
 
 import javax.annotation.processing.SupportedSourceVersion;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
 import static javax.lang.model.SourceVersion.*;
 
 /**
@@ -90,4 +91,17 @@
     protected SimpleElementVisitor9(R defaultValue){
         super(defaultValue);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by calling {@code
+     * defaultAction}.
+     *
+     * @param e the element to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of {@code defaultAction}
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return defaultAction(e, p);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java b/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java
index f916c43..ed63244 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -28,6 +28,7 @@
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.Set;
 import javax.tools.JavaFileObject.Kind;
 
@@ -163,4 +164,24 @@
     public void close() throws IOException {
         fileManager.close();
     }
+
+    public Location getModuleLocation(Location location, String moduleName) throws IOException {
+        return fileManager.getModuleLocation(location, moduleName);
+    }
+
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        return fileManager.getModuleLocation(location, fo, pkgName);
+    }
+
+    public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws  IOException {
+        return fileManager.getServiceLoader(location, service);
+    }
+
+    public String inferModuleName(Location location) throws IOException {
+        return fileManager.inferModuleName(location);
+    }
+
+    public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        return fileManager.listModuleLocations(location);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java b/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java
index e5e911e..bc1633a 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,9 @@
 import java.io.Flushable;
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.ServiceLoader;
 import java.util.Set;
+
 import static javax.tools.JavaFileObject.Kind;
 
 /**
@@ -124,6 +126,17 @@
          * @return true if this is an output location, false otherwise
          */
         boolean isOutputLocation();
+
+        /**
+         * Indicates if this location is expected to contain modules,
+         * as compared to a location which contains packages and classes.
+         *
+         * @return true if this location is expected to contain modules
+         * @since 9
+         */
+        default boolean isModuleLocation() {
+            return false;
+        }
     }
 
     /**
@@ -385,6 +398,7 @@
      * @throws IOException if an I/O error occurred
      * @see #close
      */
+    @Override
     void flush() throws IOException;
 
     /**
@@ -398,5 +412,84 @@
      * @throws IOException if an I/O error occurred
      * @see #flush
      */
+    @Override
     void close() throws IOException;
+
+    /**
+     * Gets a location for a named module within a module-oriented location.
+     *
+     * @param location the module-oriented location
+     * @param moduleName the name of the module to be found
+     * @return the location for the named module
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default Location getModuleLocation(Location location, String moduleName) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Gets a location for the module containing a specific file representing a Java
+     * source or class.
+     *
+     * @param location a module-oriented location
+     * @param fo the file
+     * @param pkgName the package name for the class(es) defined in this file
+     * @return the module containing the file
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get a service loader for a specific service class from a given location.
+     *
+     * @param location the location
+     * @param service  the {@code Class} object of the service class
+     * @param <S> the service class
+     * @return a service loader for the given service class
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws  IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Infer the name of the module from its location, as returned by
+     * getModuleLocation or listModuleLocations.
+     *
+     * @param location a location representing a module
+     * @return the name of the module
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default String inferModuleName(Location location) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Lists the modules in a module-oriented location.
+     *
+     * @param location  the location for which to list the modules
+     * @return  a series of sets of locations containing modules
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java b/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java
index 199f22d..9ca72e0 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -63,6 +63,12 @@
     ANNOTATION_PROCESSOR_PATH,
 
     /**
+     * Location to search for modules containing annotation processors.
+     * @since 9
+     */
+    ANNOTATION_PROCESSOR_MODULE_PATH,
+
+    /**
      * Location to search for platform classes.  Sometimes called
      * the boot class path.
      */
@@ -72,7 +78,31 @@
      * Location of new native header files.
      * @since 1.8
      */
-    NATIVE_HEADER_OUTPUT;
+    NATIVE_HEADER_OUTPUT,
+
+    /**
+     * Location to search for the source code of modules.
+     * @since 9
+     */
+    MODULE_SOURCE_PATH,
+
+    /**
+     * Location to search for upgradeable system modules.
+     * @since 9
+     */
+    UPGRADE_MODULE_PATH,
+
+    /**
+     * Location to search for system modules.
+     * @since 9
+     */
+    SYSTEM_MODULES,
+
+    /**
+     * Location to search for precompiled user modules.
+     * @since 9
+     */
+    MODULE_PATH;
 
     /**
      * Returns a location object with the given name.  The following
@@ -90,8 +120,11 @@
             for (Location location : values())
                 locations.putIfAbsent(location.getName(), location);
         }
-        locations.putIfAbsent(name.toString(/* null-check */), new Location() {
+        name.getClass(); /* null-check */
+        locations.putIfAbsent(name, new Location() {
+                @Override
                 public String getName() { return name; }
+                @Override
                 public boolean isOutputLocation() { return name.endsWith("_OUTPUT"); }
             });
         return locations.get(name);
@@ -100,8 +133,10 @@
         private static final ConcurrentMap<String,Location> locations
             = new ConcurrentHashMap<>();
 
+    @Override
     public String getName() { return name(); }
 
+    @Override
     public boolean isOutputLocation() {
         switch (this) {
             case CLASS_OUTPUT:
@@ -112,4 +147,18 @@
                 return false;
         }
     }
+
+    @Override
+    public boolean isModuleLocation() {
+        switch (this) {
+            case MODULE_SOURCE_PATH:
+            case ANNOTATION_PROCESSOR_MODULE_PATH:
+            case UPGRADE_MODULE_PATH:
+            case SYSTEM_MODULES:
+            case MODULE_PATH:
+                return true;
+            default:
+                return false;
+        }
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java
index 447c964..1909ce4 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java
@@ -25,10 +25,11 @@
 
 package javax.tools;
 
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Map;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * Provides methods for locating tool providers, for example,
@@ -40,8 +41,8 @@
  */
 public class ToolProvider {
 
-    private static final String systemJavaCompilerName
-        = "com.sun.tools.javac.api.JavacTool";
+    private static final String systemJavaCompilerModule = "jdk.compiler";
+    private static final String systemJavaCompilerName   = "com.sun.tools.javac.api.JavacTool";
 
     /**
      * Returns the Java&trade; programming language compiler provided
@@ -52,13 +53,17 @@
      * {@linkplain java.nio.file.FileSystem filesystem}.</p>
      * @return the compiler provided with this platform or
      * {@code null} if no compiler is provided
+     * @implNote This implementation returns the compiler provided
+     * by the {@code jdk.compiler} module if that module is available,
+     * and null otherwise.
      */
     public static JavaCompiler getSystemJavaCompiler() {
-        return instance().getSystemTool(JavaCompiler.class, systemJavaCompilerName);
+        return getSystemTool(JavaCompiler.class,
+                systemJavaCompilerModule, systemJavaCompilerName);
     }
 
-    private static final String systemDocumentationToolName
-        = "jdk.javadoc.internal.api.JavadocTool";
+    private static final String systemDocumentationToolModule = "jdk.javadoc";
+    private static final String systemDocumentationToolName = "jdk.javadoc.internal.api.JavadocTool";
 
     /**
      * Returns the Java&trade; programming language documentation tool provided
@@ -69,9 +74,13 @@
      * {@linkplain java.nio.file.FileSystem filesystem}.</p>
      * @return the documentation tool provided with this platform or
      * {@code null} if no documentation tool is provided
+     * @implNote This implementation returns the tool provided
+     * by the {@code jdk.javadoc} module if that module is available,
+     * and null otherwise.
      */
     public static DocumentationTool getSystemDocumentationTool() {
-        return instance().getSystemTool(DocumentationTool.class, systemDocumentationToolName);
+        return getSystemTool(DocumentationTool.class,
+                systemDocumentationToolModule, systemDocumentationToolName);
     }
 
     /**
@@ -87,41 +96,70 @@
         return ClassLoader.getSystemClassLoader();
     }
 
+    private static final boolean useLegacy;
 
-    private static ToolProvider instance;
-
-    private static synchronized ToolProvider instance() {
-        if (instance == null)
-            instance = new ToolProvider();
-        return instance;
-    }
-
-    // Cache for tool classes.
-    // Use weak references to avoid keeping classes around unnecessarily
-    private final Map<String, Reference<Class<?>>> toolClasses = new HashMap<>();
-
-    private ToolProvider() { }
-
-    private <T> T getSystemTool(Class<T> clazz, String name) {
-        Class<? extends T> c = getSystemToolClass(clazz, name);
+    static {
+        Class<?> c = null;
         try {
-            return c.asSubclass(clazz).newInstance();
-        } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) {
-            throw new Error(e);
+            c = Class.forName("java.lang.reflect.Module");
+        } catch (Throwable t) {
         }
+        useLegacy = (c == null);
     }
 
-    private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) {
-        Reference<Class<?>> refClass = toolClasses.get(name);
-        Class<?> c = (refClass == null ? null : refClass.get());
-        if (c == null) {
+    /**
+     * Get an instance of a system tool using the service loader.
+     * @implNote         By default, this returns the implementation in the specified module.
+     *                   For limited backward compatibility, if this code is run on an older version
+     *                   of the Java platform that does not support modules, this method will
+     *                   try and create an instance of the named class. Note that implies the
+     *                   class must be available on the system class path.
+     * @param <T>        the interface of the tool
+     * @param clazz      the interface of the tool
+     * @param moduleName the name of the module containing the desired implementation
+     * @param className  the class name of the desired implementation
+     * @return the specified implementation of the tool
+     */
+    private static <T> T getSystemTool(Class<T> clazz, String moduleName, String className) {
+        if (useLegacy) {
             try {
-                c = Class.forName(name, false, ClassLoader.getSystemClassLoader());
-            } catch (ClassNotFoundException | RuntimeException | Error e) {
+                return Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance();
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
-            toolClasses.put(name, new WeakReference<>(c));
         }
-        return c.asSubclass(clazz);
+
+        try {
+            ServiceLoader<T> sl = ServiceLoader.load(clazz, ClassLoader.getSystemClassLoader());
+            for (Iterator<T> iter = sl.iterator(); iter.hasNext(); ) {
+                T tool = iter.next();
+                if (matches(tool, moduleName))
+                    return tool;
+            }
+        } catch (ServiceConfigurationError e) {
+            throw new Error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Determine if this is tho desired tool instance.
+     * @param <T>        the interface of the tool
+     * @param tool       the instance of the tool
+     * @param moduleName the name of the module containing the desired implementation
+     * @return true if and only if the tool matches the specified criteria
+     */
+    private static <T> boolean matches(T tool, String moduleName) {
+        // for now, use reflection to implement
+        //      return moduleName.equals(tool.getClass().getModule().getName());
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object toolModule = getModuleMethod.invoke(tool.getClass());
+            Method getNameMethod = toolModule.getClass().getDeclaredMethod("getName");
+            String toolModuleName = (String) getNameMethod.invoke(toolModule);
+            return moduleName.equals(toolModuleName);
+        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
+            return false;
+        }
     }
 }
diff --git a/langtools/src/java.compiler/share/classes/module-info.java b/langtools/src/java.compiler/share/classes/module-info.java
new file mode 100644
index 0000000..c835200
--- /dev/null
+++ b/langtools/src/java.compiler/share/classes/module-info.java
@@ -0,0 +1,37 @@
+/*
+ * 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
+ * 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 java.compiler {
+    exports javax.annotation.processing;
+    exports javax.lang.model;
+    exports javax.lang.model.element;
+    exports javax.lang.model.type;
+    exports javax.lang.model.util;
+    exports javax.tools;
+
+    uses javax.tools.DocumentationTool;
+    uses javax.tools.JavaCompiler;
+}
+
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java
new file mode 100644
index 0000000..dc4f6b3
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+/**
+ * A super-type for all the directives in a ModuleTree.
+ */
+public interface DirectiveTree extends Tree { }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java
new file mode 100644
index 0000000..aeaef2b
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+import java.util.List;
+
+/**
+ * A tree node for an 'exports' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    exports <em>package-name</em>;
+ *    exports <em>package-name</em> to <em>module-name</em>;
+ * </pre>
+ *
+ * @since 9
+ */
+public interface ExportsTree extends DirectiveTree {
+    /**
+     * Returns the name of the package to be exported.
+     * @return  the name of the package to be exported
+     */
+    ExpressionTree getExportName();
+
+    /**
+     * Returns the names of the modules to which the package is exported,
+     * or null, if the package is exported to all modules.
+     *
+     * @return the names of the modules to which the package is exported, or null
+     */
+    List<? extends ExpressionTree> getModuleNames();
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java
new file mode 100644
index 0000000..bcfa6ef
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+import java.util.List;
+
+
+/**
+ * A tree node for a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    module <em>module-name</em> {
+ *        <em>directives</em>
+ *    }
+ * </pre>
+ *
+ * @since 9
+ */
+public interface ModuleTree extends Tree {
+    /**
+     * Returns the name of the module.
+     * @return the name of the module
+     */
+    ExpressionTree getName();
+
+    /**
+     * Returns the directives in the module declaration.
+     * @return the directives in the module declaration
+     */
+    List<? extends DirectiveTree> getDirectives();
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java
new file mode 100644
index 0000000..3189f3f
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+/**
+ * A tree node for a 'provides' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    provides <em>service-name</em> with <em>implementation-name</em>;
+ * </pre>
+
+ * @since 9
+ */
+public interface ProvidesTree extends DirectiveTree {
+    /**
+     * Returns the name of the service type being provided.
+     * @return the name of the service type being provided
+     */
+    ExpressionTree getServiceName();
+
+    /**
+     * Returns the name of the implementation type being provided.
+     * @return the name of the implementation type being provided
+     */
+    ExpressionTree getImplementationName();
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java
new file mode 100644
index 0000000..9a5f55c
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+/**
+ * A tree node for a 'requires' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    requires <em>module-name</em>;
+ *    requires public <em>module-name</em>;
+ * </pre>
+ *
+ * @since 9
+ */
+public interface RequiresTree extends DirectiveTree {
+    /**
+     * Returns true if this is a "requires public" directive.
+     * @return true if this is a "requires public" directive
+     */
+    boolean isPublic();
+
+    /**
+     * Returns the name of the module that is required.
+     * @return the name of the module that is required
+     */
+    ExpressionTree getModuleName();
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
index bdd0f53..73f1fd4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -604,6 +604,35 @@
         ANNOTATION_TYPE(ClassTree.class),
 
         /**
+         * Used for instances of {@link ModuleTree} representing module declarations.
+         */
+        MODULE(ModuleTree.class),
+
+        /**
+         * Used for instances of {@link ExportsTree} representing
+         * export directives in a module declaration.
+         */
+        EXPORTS(ExportsTree.class),
+
+        /**
+         * Used for instances of {@link ProvidesTree} representing
+         * export directives in a module declaration.
+         */
+        PROVIDES(ProvidesTree.class),
+
+        /**
+         * Used for instances of {@link RequiresTree} representing
+         * export directives in a module declaration.
+         */
+        REQUIRES(RequiresTree.class),
+
+        /**
+         * Used for instances of {@link UsesTree} representing
+         * export directives in a module declaration.
+         */
+        USES(UsesTree.class),
+
+        /**
          * An implementation-reserved node. This is the not the node
          * you are looking for.
          */
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
index 30d2a32..f1f951e 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -482,6 +482,46 @@
     R visitWildcard(WildcardTree node, P p);
 
     /**
+     * Visits a ModuleTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitModule(ModuleTree node, P p);
+
+    /**
+     * Visits an ExportsTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitExports(ExportsTree node, P p);
+
+    /**
+     * Visits a ProvidesTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitProvides(ProvidesTree node, P p);
+
+    /**
+     * Visits a RequiresTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitRequires(RequiresTree node, P p);
+
+    /**
+     * Visits a UsesTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitUses(UsesTree node, P p);
+
+    /**
      * Visits an unknown type of Tree node.
      * This can occur if the language evolves and new kinds
      * of nodes are added to the {@code Tree} hierarchy.
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java
new file mode 100644
index 0000000..9b52eb2
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+/**
+ * A tree node for a 'uses' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    uses <em>service-name</em>;
+ * </pre>
+ *
+ * @since 9
+ */
+public interface UsesTree extends DirectiveTree {
+    /**
+     * Returns the name of the service type.
+     * @return  the name of the service type
+     */
+    ExpressionTree getServiceName();
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
index a7e5740..0b13ca7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -719,14 +719,30 @@
         return defaultAction(node, p);
     }
 
-    /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
-     *
-     * @param node {@inheritDoc}
-     * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
-     */
+    public R visitModule(ModuleTree node, P p) {
+        return defaultAction(node, p);
+    }
+
     @Override
+    public R visitExports(ExportsTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
+    public R visitProvides(ProvidesTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
+    public R visitRequires(RequiresTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
+    public R visitUses(UsesTree node, P p) {
+        return defaultAction(node, p);
+    }
+
     public R visitErroneous(ErroneousTree node, P p) {
         return defaultAction(node, p);
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
index 3e37f6f..3751154 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -846,6 +846,32 @@
         return r;
     }
 
+    public R visitModule(ModuleTree node, P p) {
+        R r = scan(node.getName(), p);
+        r = scanAndReduce(node.getDirectives(), p, r);
+        return r;
+    }
+
+    public R visitExports(ExportsTree node, P p) {
+        R r = scan(node.getExportName(), p);
+        r = scanAndReduce(node.getModuleNames(), p, r);
+        return r;
+    }
+
+    public R visitProvides(ProvidesTree node, P p) {
+        R r = scan(node.getServiceName(), p);
+        r = scanAndReduce(node.getImplementationName(), p, r);
+        return r;
+    }
+
+    public R visitRequires(RequiresTree node, P p) {
+        return scan(node.getModuleName(), p);
+    }
+
+    public R visitUses(UsesTree node, P p) {
+        return scan(node.getServiceName(), p);
+    }
+
     /**
      * {@inheritDoc} This implementation returns {@code null}.
      *
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java
index 9559d4a..186b6e8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java
@@ -195,6 +195,9 @@
                 } else {
                     throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
                 }
+            } else if ((arg.equals("-target") || arg.equals("-source")) && i + 1 < args.length) {
+                javacOpts.add(arg);
+                javacOpts.add(args[++i]);
             } else if (arg.equals(STATS)) {
                 env.messages.setStatsEnabled(true);
             } else if (arg.equals("-bootclasspath") && i + 1 < args.length) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
index 0b958a6..e73f28c 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -28,6 +28,7 @@
 import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.Locale;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -57,7 +58,6 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.PropagatedException;
-import com.sun.tools.javac.util.ServiceLoader;
 
 /**
  * Provides basic functionality for implementations of JavacTask.
@@ -195,8 +195,7 @@
 
         Set<List<String>> pluginsToCall = new LinkedHashSet<>(pluginOpts);
         JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context);
-        ClassLoader cl = pEnv.getProcessorClassLoader();
-        ServiceLoader<Plugin> sl = ServiceLoader.load(Plugin.class, cl);
+        ServiceLoader<Plugin> sl = pEnv.getServiceLoader(Plugin.class);
         for (Plugin plugin : sl) {
             for (List<String> p : pluginsToCall) {
                 if (plugin.getName().equals(p.head)) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
index 439c2cc..3bdd316 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -36,6 +36,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.net.URI;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -347,6 +348,50 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public Location getModuleLocation(Location location, String moduleName) throws IOException {
+            try {
+                return clientJavaFileManager.getModuleLocation(location, moduleName);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+            try {
+                return clientJavaFileManager.getModuleLocation(location, fo, pkgName);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public String inferModuleName(Location location) throws IOException {
+            try {
+                return clientJavaFileManager.inferModuleName(location);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+            try {
+                return clientJavaFileManager.listModuleLocations(location);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public int isSupportedOption(String option) {
             try {
                 return clientJavaFileManager.isSupportedOption(option);
@@ -381,6 +426,17 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(Iterable<? extends Path> paths) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromPaths(paths);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
             try {
                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(files);
@@ -392,6 +448,17 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(paths);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
             try {
                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromStrings(names);
@@ -414,9 +481,20 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
-        public void setLocation(Location location, Iterable<? extends File> path) throws IOException {
+        public void setLocation(Location location, Iterable<? extends File> files) throws IOException {
             try {
-                ((StandardJavaFileManager)clientJavaFileManager).setLocation(location, path);
+                ((StandardJavaFileManager)clientJavaFileManager).setLocation(location, files);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public void setLocationFromPaths(Location location, Iterable<? extends Path> paths) throws IOException {
+            try {
+                ((StandardJavaFileManager)clientJavaFileManager).setLocationFromPaths(location, paths);
             } catch (ClientCodeException e) {
                 throw e;
             } catch (RuntimeException | Error e) {
@@ -434,6 +512,28 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Iterable<? extends Path> getLocationAsPaths(Location location) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).getLocationAsPaths(location);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Path asPath(FileObject file) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).asPath(file);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
     }
 
     protected class WrappedFileObject implements FileObject {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
index 1a17ec0..384dadc 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -33,12 +33,17 @@
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
 import javax.tools.*;
+import javax.tools.JavaFileObject.Kind;
 
 import com.sun.source.tree.*;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.comp.*;
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.main.*;
@@ -49,6 +54,8 @@
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
+import com.sun.tools.javac.tree.JCTree.Tag;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.List;
@@ -253,7 +260,7 @@
      * @return a list of elements corresponding to the top level
      * classes in the abstract syntax trees
      */
-    public Iterable<? extends TypeElement> enter() {
+    public Iterable<? extends Element> enter() {
         return enter(null);
     }
 
@@ -264,11 +271,13 @@
      * @return a list of elements corresponding to the top level
      * classes in the abstract syntax trees
      */
-    public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees)
+    public Iterable<? extends Element> enter(Iterable<? extends CompilationUnitTree> trees)
     {
         if (trees == null && notYetEntered != null && notYetEntered.isEmpty())
             return List.nil();
 
+        boolean wasInitialized = compiler != null;
+
         prepareCompiler(true);
 
         ListBuffer<JCCompilationUnit> roots = null;
@@ -305,22 +314,38 @@
             }
         }
 
-        if (roots == null)
+        if (roots == null) {
+            if (trees == null && !wasInitialized) {
+                compiler.initModules(List.nil());
+            }
             return List.nil();
+        }
+
+        List<JCCompilationUnit> units = compiler.initModules(roots.toList());
 
         try {
-            List<JCCompilationUnit> units = compiler.enterTrees(roots.toList());
+            units = compiler.enterTrees(units);
 
             if (notYetEntered.isEmpty())
                 compiler.processAnnotations(units);
 
-            ListBuffer<TypeElement> elements = new ListBuffer<>();
+            ListBuffer<Element> elements = new ListBuffer<>();
             for (JCCompilationUnit unit : units) {
-                for (JCTree node : unit.defs) {
-                    if (node.hasTag(JCTree.Tag.CLASSDEF)) {
-                        JCClassDecl cdef = (JCClassDecl) node;
-                        if (cdef.sym != null) // maybe null if errors in anno processing
-                            elements.append(cdef.sym);
+                boolean isPkgInfo = unit.sourcefile.isNameCompatible("package-info",
+                                                                     JavaFileObject.Kind.SOURCE);
+                if (isPkgInfo) {
+                    elements.append(unit.packge);
+                } else {
+                    for (JCTree node : unit.defs) {
+                        if (node.hasTag(JCTree.Tag.CLASSDEF)) {
+                            JCClassDecl cdef = (JCClassDecl) node;
+                            if (cdef.sym != null) // maybe null if errors in anno processing
+                                elements.append(cdef.sym);
+                        } else if (node.hasTag(JCTree.Tag.MODULEDEF)) {
+                            JCModuleDecl mdef = (JCModuleDecl) node;
+                            if (mdef.sym != null)
+                                elements.append(mdef.sym);
+                        }
                     }
                 }
             }
@@ -353,7 +378,7 @@
     // This implementation requires that we open up privileges on JavaCompiler.
     // An alternative implementation would be to move this code to JavaCompiler and
     // wrap it here
-    public Iterable<? extends Element> analyze(Iterable<? extends TypeElement> classes) {
+    public Iterable<? extends Element> analyze(Iterable<? extends Element> classes) {
         enter(null);  // ensure all classes have been entered
 
         final ListBuffer<Element> results = new ListBuffer<>();
@@ -383,8 +408,13 @@
                         if (cdef.sym != null)
                             elems.append(cdef.sym);
                         break;
-                    case TOPLEVEL:
-                        JCCompilationUnit unit = (JCCompilationUnit) env.tree;
+                    case MODULEDEF:
+                        JCModuleDecl mod = (JCModuleDecl) env.tree;
+                        if (mod.sym != null)
+                            elems.append(mod.sym);
+                        break;
+                    case PACKAGEDEF:
+                        JCCompilationUnit unit = env.toplevel;
                         if (unit.packge != null)
                             elems.append(unit.packge);
                         break;
@@ -413,7 +443,7 @@
      * @param classes a list of class elements
      * @return the files that were generated
      */
-    public Iterable<? extends JavaFileObject> generate(Iterable<? extends TypeElement> classes) {
+    public Iterable<? extends JavaFileObject> generate(Iterable<? extends Element> classes) {
         final ListBuffer<JavaFileObject> results = new ListBuffer<>();
         try {
             analyze(null);  // ensure all classes have been parsed, entered, and analyzed
@@ -447,17 +477,33 @@
         return TreeInfo.pathFor((JCTree) node, (JCTree.JCCompilationUnit) unit).reverse();
     }
 
+    public void ensureEntered() {
+        args.allowEmpty();
+        enter(null);
+    }
+
     abstract class Filter {
-        void run(Queue<Env<AttrContext>> list, Iterable<? extends TypeElement> classes) {
-            Set<TypeElement> set = new HashSet<>();
-            for (TypeElement item: classes)
+        void run(Queue<Env<AttrContext>> list, Iterable<? extends Element> elements) {
+            Set<Element> set = new HashSet<>();
+            for (Element item: elements) {
                 set.add(item);
+            }
 
             ListBuffer<Env<AttrContext>> defer = new ListBuffer<>();
             while (list.peek() != null) {
                 Env<AttrContext> env = list.remove();
-                ClassSymbol csym = env.enclClass.sym;
-                if (csym != null && set.contains(csym.outermostClass()))
+                Symbol test = null;
+
+                if (env.tree.hasTag(Tag.MODULEDEF)) {
+                    test = ((JCModuleDecl) env.tree).sym;
+                } else if (env.tree.hasTag(Tag.PACKAGEDEF)) {
+                    test = env.toplevel.packge;
+                } else {
+                    ClassSymbol csym = env.enclClass.sym;
+                    if (csym != null)
+                        test = csym.outermostClass();
+                }
+                if (test != null && set.contains(test))
                     process(env);
                 else
                     defer = defer.append(env);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java
index 99b7982..bc750f2 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -129,9 +129,17 @@
             }
 
             if (classes != null) {
-                for (String cls : classes)
-                    if (!SourceVersion.isName(cls)) // implicit null check
+                for (String cls : classes) {
+                    int sep = cls.indexOf('/'); // implicit null check
+                    if (sep > 0) {
+                        String mod = cls.substring(0, sep);
+                        if (!SourceVersion.isName(mod))
+                            throw new IllegalArgumentException("Not a valid module name: " + mod);
+                        cls = cls.substring(sep + 1);
+                    }
+                    if (!SourceVersion.isName(cls))
                         throw new IllegalArgumentException("Not a valid class name: " + cls);
+                }
             }
 
             if (compilationUnits != null) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
index d75f6f2..abd811b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
@@ -76,6 +76,7 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
@@ -92,6 +93,7 @@
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
 import com.sun.tools.javac.comp.MemberEnter;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.comp.Resolve;
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.model.JavacElements;
@@ -156,6 +158,7 @@
 public class JavacTrees extends DocTrees {
 
     // in a world of a single context per compilation, these would all be final
+    private Modules modules;
     private Resolve resolve;
     private Enter enter;
     private Log log;
@@ -206,6 +209,7 @@
     }
 
     private void init(Context context) {
+        modules = Modules.instance(context);
         attr = Attr.instance(context);
         enter = Enter.instance(context);
         elements = JavacElements.instance(context);
@@ -434,21 +438,31 @@
                 // and if not, then we check to see if it identifies a package.
                 Type t = attr.attribType(ref.qualifierExpression, env);
                 if (t.isErroneous()) {
-                    if (ref.memberName == null) {
-                        // Attr/Resolve assume packages exist and create symbols as needed
-                        // so use getPackageElement to restrict search to existing packages
-                        PackageSymbol pck = elements.getPackageElement(ref.qualifierExpression.toString());
-                        if (pck != null) {
-                            return pck;
-                        } else if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
+                    JCCompilationUnit toplevel =
+                        treeMaker.TopLevel(List.<JCTree>nil());
+                    final ModuleSymbol msym = modules.getDefaultModule();
+                    toplevel.modle = msym;
+                    toplevel.packge = msym.unnamedPackage;
+                    Symbol sym = attr.attribIdent(ref.qualifierExpression, toplevel);
+
+                    sym.complete();
+
+                    if ((sym.kind == PCK || sym.kind == TYP) && sym.exists()) {
+                        tsym = (TypeSymbol) sym;
+                        memberName = (Name) ref.memberName;
+                        if (sym.kind == PCK && memberName != null) {
+                            //cannot refer to a package "member"
+                            return null;
+                        }
+                    } else {
+                        if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
                             // fixup:  allow "identifier" instead of "#identifier"
                             // for compatibility with javadoc
                             tsym = env.enclClass.sym;
                             memberName = ((JCIdent) ref.qualifierExpression).name;
-                        } else
+                        } else {
                             return null;
-                    } else {
-                        return null;
+                        }
                     }
                 } else {
                     tsym = t.tsym;
@@ -1179,7 +1193,8 @@
             }
         };
 
-        PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo, syms.unnamedPackage);
+        PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo,
+                syms.unnamedModule.unnamedPackage);
 
         jcCompilationUnit.docComments = new DocCommentTable() {
             @Override
@@ -1209,13 +1224,12 @@
 
         };
         jcCompilationUnit.lineMap = jcCompilationUnit.getLineMap();
+        jcCompilationUnit.modle = psym.modle;
+        jcCompilationUnit.sourcefile = jfo;
         jcCompilationUnit.namedImportScope = new NamedImportScope(psym, jcCompilationUnit.toplevelScope);
         jcCompilationUnit.packge = psym;
-        jcCompilationUnit.starImportScope = null;
-        jcCompilationUnit.sourcefile = jfo;
         jcCompilationUnit.starImportScope = new StarImportScope(psym);
         jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
-
         return new TreePath(jcCompilationUnit);
     }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
index 466a41d..047eaa3 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
@@ -37,11 +37,13 @@
 import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
 
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.comp.Annotate;
@@ -118,6 +120,10 @@
      */
     final Name completionFailureName;
 
+    /** Module specified with -Xmodule:
+     */
+    final Name moduleOverride;
+
     /** Access to files
      */
     private final JavaFileManager fileManager;
@@ -178,7 +184,7 @@
         return instance;
     }
 
-    /** Construct a new class reader. */
+    /** Construct a new class finder. */
     protected ClassFinder(Context context) {
         context.put(classFinderKey, this);
         reader = ClassReader.instance(context);
@@ -205,6 +211,9 @@
             ? names.fromString(options.get("failcomplete"))
             : null;
 
+        moduleOverride = options.isSet(XMODULE) ? names.fromString(options.get(XMODULE))
+                                                : null;
+
         // Temporary, until more info is available from the module system.
         boolean useCtProps;
         JavaFileManager fm = context.get(JavaFileManager.class);
@@ -237,7 +246,7 @@
      * available from the module system.
      */
     long getSupplementaryFlags(ClassSymbol c) {
-        if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile)) {
+        if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) {
             return 0;
         }
 
@@ -318,7 +327,7 @@
             for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
                 Symbol encl = owner.members().findFirst(name);
                 if (encl == null)
-                    encl = syms.classes.get(TypeSymbol.formFlatName(name, owner));
+                    encl = syms.getClass(c.packge().modle, TypeSymbol.formFlatName(name, owner));
                 if (encl != null)
                     encl.complete();
             }
@@ -328,7 +337,7 @@
     /** Fill in definition of class `c' from corresponding class or
      *  source file.
      */
-    private void fillIn(ClassSymbol c) {
+    void fillIn(ClassSymbol c) {
         if (completionFailureName == c.fullname) {
             throw new CompletionFailure(c, "user-selected completion failure by class name");
         }
@@ -397,14 +406,21 @@
     /** Load a toplevel class with given fully qualified name
      *  The class is entered into `classes' only if load was successful.
      */
-    public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
-        boolean absent = syms.classes.get(flatname) == null;
-        ClassSymbol c = syms.enterClass(flatname);
+    public ClassSymbol loadClass(ModuleSymbol msym, Name flatname) throws CompletionFailure {
+        Assert.checkNonNull(msym);
+        Name packageName = Convert.packagePart(flatname);
+        PackageSymbol ps = syms.lookupPackage(msym, packageName);
+
+        Assert.checkNonNull(ps.modle, () -> "msym=" + msym + "; flatName=" + flatname);
+
+        boolean absent = syms.getClass(ps.modle, flatname) == null;
+        ClassSymbol c = syms.enterClass(ps.modle, flatname);
+
         if (c.members_field == null) {
             try {
                 c.complete();
             } catch (CompletionFailure ex) {
-                if (absent) syms.classes.remove(flatname);
+                if (absent) syms.removeClass(ps.modle, flatname);
                 throw ex;
             }
         }
@@ -438,7 +454,7 @@
             ? p.package_info
             : (ClassSymbol) p.members_field.findFirst(classname);
         if (c == null) {
-            c = syms.enterClass(classname, p);
+            c = syms.enterClass(p.modle, classname, p);
             if (c.classfile == null) // only update the file if's it's newly created
                 c.classfile = file;
             if (isPkgInfo) {
@@ -479,6 +495,7 @@
     /**
      * specifies types of files to be read when filling in a package symbol
      */
+    // Note: overridden by JavadocClassFinder
     protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
         return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
     }
@@ -502,16 +519,83 @@
         if (p.members_field == null)
             p.members_field = WriteableScope.create(p);
 
-        preferCurrent = false;
-        if (userPathsFirst) {
+        ModuleSymbol msym = p.modle;
+
+        Assert.checkNonNull(msym, () -> p.toString());
+
+        msym.complete();
+
+        if (msym == syms.noModule) {
+            preferCurrent = false;
+            if (userPathsFirst) {
+                scanUserPaths(p);
+                preferCurrent = true;
+                scanPlatformPath(p);
+            } else {
+                scanPlatformPath(p);
+                scanUserPaths(p);
+            }
+        } else if (msym.classLocation == StandardLocation.CLASS_PATH) {
+            // assert p.modle.sourceLocation == StandardLocation.SOURCE_PATH);
             scanUserPaths(p);
-            preferCurrent = true;
-            scanPlatformPath(p);
         } else {
-            scanPlatformPath(p);
-            scanUserPaths(p);
+            scanModulePaths(p, msym);
         }
-        verbosePath = false;
+    }
+
+    // TODO: for now, this is a much simplified form of scanUserPaths
+    // and (deliberately) does not default sourcepath to classpath.
+    // But, we need to think about retaining existing behavior for
+    // -classpath and -sourcepath for single module mode.
+    // One plausible solution is to detect if the module's sourceLocation
+    // is the same as the module's classLocation.
+    private void scanModulePaths(PackageSymbol p, ModuleSymbol msym) throws IOException {
+        Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
+
+        Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
+        classKinds.remove(JavaFileObject.Kind.SOURCE);
+        boolean wantClassFiles = !classKinds.isEmpty();
+
+        Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
+        sourceKinds.remove(JavaFileObject.Kind.CLASS);
+        boolean wantSourceFiles = !sourceKinds.isEmpty();
+
+        String packageName = p.fullname.toString();
+
+        if (msym.name == moduleOverride) {
+            if (wantClassFiles) {
+                fillIn(p, CLASS_PATH,
+                       fileManager.list(CLASS_PATH,
+                                        packageName,
+                                        classKinds,
+                                        false));
+            }
+            if (wantSourceFiles && fileManager.hasLocation(SOURCE_PATH)) {
+                fillIn(p, SOURCE_PATH,
+                        fileManager.list(SOURCE_PATH,
+                                        packageName,
+                                        sourceKinds,
+                                        false));
+            }
+        }
+
+        Location classLocn = msym.classLocation;
+        Location sourceLocn = msym.sourceLocation;
+
+        if (wantClassFiles && (classLocn != null)) {
+            fillIn(p, classLocn,
+                   fileManager.list(classLocn,
+                                    packageName,
+                                    classKinds,
+                                    false));
+        }
+        if (wantSourceFiles && (sourceLocn != null)) {
+            fillIn(p, sourceLocn,
+                   fileManager.list(sourceLocn,
+                                    packageName,
+                                    sourceKinds,
+                                    false));
+        }
     }
 
     /**
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
new file mode 100644
index 0000000..9867b00
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+package com.sun.tools.javac.code;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.util.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.List;
+
+
+/**
+ *  Root class for the directives that may appear in module compilation units.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public abstract class Directive implements ModuleElement.Directive {
+
+    /** Flags for RequiresDirective. */
+    public enum RequiresFlag {
+        PUBLIC(0x0020),
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000),
+        EXTRA(0x10000);
+
+        // overkill? move to ClassWriter?
+        public static int value(Set<RequiresFlag> s) {
+            int v = 0;
+            for (RequiresFlag f: s)
+                v |= f.value;
+            return v;
+        }
+
+        RequiresFlag(int value) {
+            this.value = value;
+        }
+
+        public final int value;
+    }
+
+    /**
+     * 'exports' Package ';'
+     */
+    public static class ExportsDirective extends Directive
+            implements ModuleElement.ExportsDirective {
+        public final PackageSymbol packge;
+        public final List<ModuleSymbol> modules;
+
+        public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
+            this.packge = packge;
+            this.modules = modules;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.EXPORTS;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public PackageElement getPackage() {
+            return packge;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public java.util.List<? extends ModuleElement> getTargetModules() {
+            return Collections.unmodifiableList(modules);
+        }
+
+        @Override
+        public String toString() {
+            if (modules == null)
+                return "Exports[" + packge + "]";
+            else
+                return "Exports[" + packge + ":" + modules + "]";
+        }
+    }
+
+    /**
+     * 'provides' ServiceName 'with' QualifiedIdentifer ';'
+     */
+    public static class ProvidesDirective extends Directive
+            implements ModuleElement.ProvidesDirective {
+        public final ClassSymbol service;
+        public final ClassSymbol impl;
+
+        public ProvidesDirective(ClassSymbol service, ClassSymbol impl) {
+            this.service = service;
+            this.impl = impl;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.PROVIDES;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public TypeElement getService() {
+            return service;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public TypeElement getImplementation() {
+            return impl;
+        }
+
+        @Override
+        public String toString() {
+            return "Provides[" + service + "," + impl + "]";
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof ProvidesDirective)) {
+                return false;
+            }
+            ProvidesDirective other = (ProvidesDirective)obj;
+            return service == other.service && impl == other.impl;
+        }
+
+        @Override
+        public int hashCode() {
+            return service.hashCode() * 31 + impl.hashCode() * 37;
+        }
+    }
+
+    /**
+     * 'requires' ['public'] ModuleName ';'
+     */
+    public static class RequiresDirective extends Directive
+            implements ModuleElement.RequiresDirective {
+        public final ModuleSymbol module;
+        public final Set<RequiresFlag> flags;
+
+        public RequiresDirective(ModuleSymbol module) {
+            this(module, EnumSet.noneOf(RequiresFlag.class));
+        }
+
+        public RequiresDirective(ModuleSymbol module, Set<RequiresFlag> flags) {
+            this.module = module;
+            this.flags = flags;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.REQUIRES;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public boolean isPublic() {
+            return flags.contains(RequiresFlag.PUBLIC);
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement getDependency() {
+            return module;
+        }
+
+        @Override
+        public String toString() {
+            return "Requires[" + flags + "," + module + "]";
+        }
+    }
+
+    /**
+     * 'uses' ServiceName ';'
+     */
+    public static class UsesDirective extends Directive
+            implements ModuleElement.UsesDirective {
+        public final ClassSymbol service;
+
+        public UsesDirective(ClassSymbol service) {
+            this.service = service;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.USES;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public TypeElement getService() {
+            return service;
+        }
+
+        @Override
+        public String toString() {
+            return "Uses[" + service + "]";
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof UsesDirective)) {
+                return false;
+            }
+            UsesDirective other = (UsesDirective)obj;
+            return service == other.service;
+        }
+
+        @Override
+        public int hashCode() {
+            return service.hashCode() * 31;
+        }
+    }
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
index 02cf124..5aa826e 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
@@ -107,6 +107,7 @@
     public static final int ACC_SUPER    = 0x0020;
     public static final int ACC_BRIDGE   = 0x0040;
     public static final int ACC_VARARGS  = 0x0080;
+    public static final int ACC_MODULE   = 0x8000;
 
     /*****************************************
      * Internal compiler flags (no bits in the lower 16).
@@ -277,6 +278,21 @@
      */
     public static final long TYPE_TRANSLATED = 1L<<50;
 
+    /**
+     * Flag to indicate class symbol is for module-info
+     */
+    public static final long MODULE = 1L<<51;
+
+    /**
+     * Flag to indicate the given ModuleSymbol is an automatic module.
+     */
+    public static final long AUTOMATIC_MODULE = 1L<<52;
+
+    /**
+     * Flag to indicate the given ModuleSymbol is a system module.
+     */
+    public static final long SYSTEM_MODULE = 1L<<53;
+
     /** Modifier masks.
      */
     public static final int
@@ -385,7 +401,8 @@
         SIGNATURE_POLYMORPHIC(Flags.SIGNATURE_POLYMORPHIC),
         THROWS(Flags.THROWS),
         LAMBDA_METHOD(Flags.LAMBDA_METHOD),
-        TYPE_TRANSLATED(Flags.TYPE_TRANSLATED);
+        TYPE_TRANSLATED(Flags.TYPE_TRANSLATED),
+        MODULE(Flags.MODULE);
 
         Flag(long flag) {
             this.value = flag;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
index 263d0c5..e98a1a4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
@@ -65,6 +65,7 @@
         VAR(Category.BASIC, KindName.VAR, KindSelector.VAR),
         MTH(Category.BASIC, KindName.METHOD, KindSelector.MTH),
         POLY(Category.BASIC, KindSelector.POLY),
+        MDL(Category.BASIC, KindSelector.MDL),
         ERR(Category.ERROR, KindSelector.ERR),
         AMBIGUOUS(Category.RESOLUTION_TARGET),                         // overloaded       target
         HIDDEN(Category.RESOLUTION_TARGET),                            // not overloaded   non-target
@@ -169,9 +170,10 @@
         public static final KindSelector VAR = new KindSelector(0x04);
         public static final KindSelector VAL = new KindSelector(0x0c);
         public static final KindSelector MTH = new KindSelector(0x10);
-        public static final KindSelector ERR = new KindSelector(0x3f);
         public static final KindSelector POLY = new KindSelector(0x20);
-        public static final KindSelector ASG = new KindSelector(0x44);
+        public static final KindSelector MDL = new KindSelector(0x40);
+        public static final KindSelector ERR = new KindSelector(0x7f);
+        public static final KindSelector ASG = new KindSelector(0x84);
 
         //common derived selectors
         public static final KindSelector TYP_PCK = of(TYP, PCK);
@@ -212,6 +214,7 @@
             if ((data & MTH.data) != 0) kinds.add(KindName.METHOD);
             if ((data & TYP.data) != 0) kinds.add(KindName.CLASS);
             if ((data & PCK.data) != 0) kinds.add(KindName.PACKAGE);
+            if ((data & MDL.data) != 0) kinds.add(KindName.MODULE);
             return kinds;
         }
     }
@@ -230,7 +233,8 @@
         CLASS("kindname.class"),
         STATIC_INIT("kindname.static.init"),
         INSTANCE_INIT("kindname.instance.init"),
-        PACKAGE("kindname.package");
+        PACKAGE("kindname.package"),
+        MODULE("kindname.module");
 
         private final String name;
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java
new file mode 100644
index 0000000..0c08c49
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.javac.code;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Fragments;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.Fragment;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.StringUtils;
+
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+/**
+ *  This class provides operations to locate module definitions
+ *  from the source and class files on the paths provided to javac.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class ModuleFinder {
+    /** The context key for the module finder. */
+    protected static final Context.Key<ModuleFinder> moduleFinderKey = new Context.Key<>();
+
+    /** The log to use for verbose output. */
+    private final Log log;
+
+    /** The symbol table. */
+    private final Symtab syms;
+
+    /** The name table. */
+    private final Names names;
+
+    private final ClassFinder classFinder;
+
+    /** Access to files
+     */
+    private final JavaFileManager fileManager;
+
+    private final JCDiagnostic.Factory diags;
+
+    /** Get the ModuleFinder instance for this invocation. */
+    public static ModuleFinder instance(Context context) {
+        ModuleFinder instance = context.get(moduleFinderKey);
+        if (instance == null)
+            instance = new ModuleFinder(context);
+        return instance;
+    }
+
+    /** Construct a new module finder. */
+    protected ModuleFinder(Context context) {
+        context.put(moduleFinderKey, this);
+        names = Names.instance(context);
+        syms = Symtab.instance(context);
+        fileManager = context.get(JavaFileManager.class);
+        log = Log.instance(context);
+        classFinder = ClassFinder.instance(context);
+
+        diags = JCDiagnostic.Factory.instance(context);
+    }
+
+    class ModuleLocationIterator implements Iterator<Set<Location>> {
+        StandardLocation outer;
+        Set<Location> next = null;
+
+        Iterator<StandardLocation> outerIter = Arrays.asList(
+                StandardLocation.MODULE_SOURCE_PATH,
+                StandardLocation.UPGRADE_MODULE_PATH,
+                StandardLocation.SYSTEM_MODULES,
+                StandardLocation.MODULE_PATH
+        ).iterator();
+        Iterator<Set<Location>> innerIter = null;
+
+        @Override
+        public boolean hasNext() {
+            while (next == null) {
+                while (innerIter == null || !innerIter.hasNext()) {
+                    if (outerIter.hasNext()) {
+                        outer = outerIter.next();
+                        try {
+                            innerIter = fileManager.listModuleLocations(outer).iterator();
+                        } catch (IOException e) {
+                            System.err.println("error listing module locations for " + outer + ": " + e);  // FIXME
+                        }
+                    } else
+                        return false;
+                }
+
+                if (innerIter.hasNext())
+                    next = innerIter.next();
+            }
+            return true;
+        }
+
+        @Override
+        public Set<Location> next() {
+            hasNext();
+            if (next != null) {
+                Set<Location> result = next;
+                next = null;
+                return result;
+            }
+            throw new NoSuchElementException();
+        }
+
+    }
+
+    ModuleLocationIterator moduleLocationIterator = new ModuleLocationIterator();
+
+    public ModuleSymbol findModule(Name name) {
+        return findModule(syms.enterModule(name));
+    }
+
+    public ModuleSymbol findModule(ModuleSymbol msym) {
+        if (msym.kind != ERR && msym.sourceLocation == null && msym.classLocation == null) {
+            // fill in location
+            List<ModuleSymbol> list = scanModulePath(msym);
+            if (list.isEmpty()) {
+                msym.kind = ERR;
+            }
+        }
+        if (msym.kind != ERR && msym.module_info.sourcefile == null && msym.module_info.classfile == null) {
+            // fill in module-info
+            findModuleInfo(msym);
+        }
+        return msym;
+    }
+
+    public List<ModuleSymbol> findAllModules() {
+        List<ModuleSymbol> list = scanModulePath(null);
+        for (ModuleSymbol msym: list) {
+            if (msym.kind != ERR && msym.module_info.sourcefile == null && msym.module_info.classfile == null) {
+                // fill in module-info
+                findModuleInfo(msym);
+            }
+        }
+        return list;
+    }
+
+    public ModuleSymbol findSingleModule() {
+        try {
+            JavaFileObject src_fo = getModuleInfoFromLocation(StandardLocation.SOURCE_PATH, Kind.SOURCE);
+            JavaFileObject class_fo = getModuleInfoFromLocation(StandardLocation.CLASS_OUTPUT, Kind.CLASS);
+            JavaFileObject fo = (src_fo == null) ? class_fo
+                    : (class_fo == null) ? src_fo
+                            : classFinder.preferredFileObject(src_fo, class_fo);
+
+            ModuleSymbol msym;
+            if (fo == null) {
+                msym = syms.unnamedModule;
+            } else {
+                // Note: the following may trigger a re-entrant call to Modules.enter
+//                msym = new ModuleSymbol();
+//                ClassSymbol info = new ClassSymbol(Flags.MODULE, names.module_info, msym);
+//                info.modle = msym;
+//                info.classfile = fo;
+//                info.members_field = WriteableScope.create(info);
+//                msym.module_info = info;
+                msym = ModuleSymbol.create(null, names.module_info);
+                msym.module_info.classfile = fo;
+                msym.completer = sym -> classFinder.fillIn(msym.module_info);
+//                // TODO: should we do the following here, or as soon as we find the name in
+//                // the source or class file?
+//                // Consider the case when the class/source path module shadows one on the
+//                // module source path
+//                if (syms.modules.get(msym.name) != null) {
+//                    // error: module already defined
+//                    System.err.println("ERROR: module already defined: " + msym);
+//                } else {
+//                    syms.modules.put(msym.name, msym);
+//                }
+            }
+
+            msym.classLocation = StandardLocation.CLASS_OUTPUT;
+            return msym;
+
+        } catch (IOException e) {
+            throw new Error(e); // FIXME
+        }
+    }
+
+    private JavaFileObject getModuleInfoFromLocation(Location location, Kind kind) throws IOException {
+        if (!fileManager.hasLocation(location))
+            return null;
+
+        return fileManager.getJavaFileForInput(location,
+                                               names.module_info.toString(),
+                                               kind);
+    }
+
+    private List<ModuleSymbol> scanModulePath(ModuleSymbol toFind) {
+        ListBuffer<ModuleSymbol> results = new ListBuffer<>();
+        Map<Name, Location> namesInSet = new HashMap<>();
+        while (moduleLocationIterator.hasNext()) {
+            Set<Location> locns = (moduleLocationIterator.next());
+            namesInSet.clear();
+            for (Location l: locns) {
+                try {
+                    Name n = names.fromString(fileManager.inferModuleName(l));
+                    if (namesInSet.put(n, l) == null) {
+                        ModuleSymbol msym = syms.enterModule(n);
+                        if (msym.sourceLocation != null || msym.classLocation != null) {
+                            // module has already been found, so ignore this instance
+                            continue;
+                        }
+                        if (moduleLocationIterator.outer == StandardLocation.MODULE_SOURCE_PATH) {
+                            msym.sourceLocation = l;
+                            if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                                msym.classLocation = fileManager.getModuleLocation(StandardLocation.CLASS_OUTPUT, msym.name.toString());
+                            }
+                        } else {
+                            msym.classLocation = l;
+                        }
+                        if (moduleLocationIterator.outer == StandardLocation.SYSTEM_MODULES ||
+                            moduleLocationIterator.outer == StandardLocation.UPGRADE_MODULE_PATH) {
+                            msym.flags_field |= Flags.SYSTEM_MODULE;
+                        }
+                        if (toFind == msym || toFind == null) {
+                            // Note: cannot return msym directly, because we must finish
+                            // processing this set first
+                            results.add(msym);
+                        }
+                    } else {
+                        log.error(Errors.DuplicateModuleOnPath(
+                                getDescription(moduleLocationIterator.outer), n));
+                    }
+                } catch (IOException e) {
+                    // skip location for now?  log error?
+                }
+            }
+            if (toFind != null && results.nonEmpty())
+                return results.toList();
+        }
+
+        return results.toList();
+    }
+
+    private void findModuleInfo(ModuleSymbol msym) {
+        try {
+            JavaFileObject src_fo = (msym.sourceLocation == null) ? null
+                    : fileManager.getJavaFileForInput(msym.sourceLocation,
+                            names.module_info.toString(), Kind.SOURCE);
+
+            JavaFileObject class_fo = (msym.classLocation == null) ? null
+                    : fileManager.getJavaFileForInput(msym.classLocation,
+                            names.module_info.toString(), Kind.CLASS);
+
+            JavaFileObject fo = (src_fo == null) ? class_fo :
+                    (class_fo == null) ? src_fo :
+                    classFinder.preferredFileObject(src_fo, class_fo);
+
+            if (fo == null) {
+                String moduleName = msym.sourceLocation == null && msym.classLocation != null ?
+                    fileManager.inferModuleName(msym.classLocation) : null;
+                if (moduleName != null) {
+                    msym.module_info.classfile = null;
+                    msym.flags_field |= Flags.AUTOMATIC_MODULE;
+                } else {
+                    msym.kind = ERR;
+                }
+            } else {
+                msym.module_info.classfile = fo;
+                msym.module_info.completer = new Symbol.Completer() {
+                    @Override
+                    public void complete(Symbol sym) throws CompletionFailure {
+                        classFinder.fillIn(msym.module_info);
+                    }
+                    @Override
+                    public String toString() {
+                        return "ModuleInfoCompleter";
+                    }
+                };
+            }
+        } catch (IOException e) {
+            msym.kind = ERR;
+        }
+    }
+
+    Fragment getDescription(StandardLocation l) {
+        switch (l) {
+            case MODULE_PATH: return Fragments.LocnModule_path;
+            case MODULE_SOURCE_PATH: return Fragments.LocnModule_source_path;
+            case SYSTEM_MODULES: return Fragments.LocnSystem_modules;
+            case UPGRADE_MODULE_PATH: return Fragments.LocnUpgrade_module_path;
+            default:
+                throw new AssertionError();
+        }
+    }
+
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java
index 8971e6c..138432b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -152,14 +152,14 @@
         if (seenCaptured.contains(t))
             return printAnnotations(t) +
                 localize(locale, "compiler.misc.type.captureof.1",
-                         capturedVarId(t, locale));
+                capturedVarId(t, locale));
         else {
             try {
                 seenCaptured = seenCaptured.prepend(t);
                 return printAnnotations(t) +
                     localize(locale, "compiler.misc.type.captureof",
-                             capturedVarId(t, locale),
-                             visit(t.wildcard, locale));
+                    capturedVarId(t, locale),
+                    visit(t.wildcard, locale));
             }
             finally {
                 seenCaptured = seenCaptured.tail;
@@ -274,6 +274,11 @@
         return visitType(t, locale);
     }
 
+    @Override
+    public String visitModuleType(ModuleType t, Locale locale) {
+        return visitType(t, locale);
+    }
+
     public String visitType(Type t, Locale locale) {
         String s = (t.tsym == null || t.tsym.name == null)
                 ? localize(locale, "compiler.misc.type.none")
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
index 6870123..aac3e76 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
@@ -137,6 +137,9 @@
     public boolean allowImprovedCatchAnalysis() {
         return compareTo(JDK1_7) >= 0;
     }
+    public boolean allowModules() {
+        return compareTo(JDK1_9) >= 0;
+    }
     public boolean allowTryWithResources() {
         return compareTo(JDK1_7) >= 0;
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
index 428a30a..c6957ff4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -27,16 +27,26 @@
 
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Inherited;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
-import javax.lang.model.element.*;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 
-import com.sun.tools.javac.code.Attribute.Compound;
-import com.sun.tools.javac.code.TypeAnnotations.AnnotationType;
-import com.sun.tools.javac.code.TypeMetadata.Entry;
-import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
+import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Type.*;
@@ -48,6 +58,7 @@
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.Name;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -843,7 +854,7 @@
             boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
                 return (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
                         anno.position.type == TargetType.METHOD_TYPE_PARAMETER) &&
-                       anno.position.parameter_index == index;
+                        anno.position.parameter_index == index;
             }
 
 
@@ -852,6 +863,122 @@
             return v.visitTypeParameter(this, p);
         }
     }
+    /** A class for module symbols.
+     */
+    public static class ModuleSymbol extends TypeSymbol
+            implements ModuleElement {
+
+        public Name version;
+        public JavaFileManager.Location sourceLocation;
+        public JavaFileManager.Location classLocation;
+
+        /** All directives, in natural order. */
+        public List<com.sun.tools.javac.code.Directive> directives;
+        public List<com.sun.tools.javac.code.Directive.RequiresDirective> requires;
+        public List<com.sun.tools.javac.code.Directive.ExportsDirective> exports;
+        public List<com.sun.tools.javac.code.Directive.ProvidesDirective> provides;
+        public List<com.sun.tools.javac.code.Directive.UsesDirective> uses;
+
+        public ClassSymbol module_info;
+
+        public PackageSymbol unnamedPackage;
+        public Map<Name, PackageSymbol> visiblePackages;
+        public List<Symbol> enclosedPackages = List.nil();
+
+        public Completer usesProvidesCompleter = Completer.NULL_COMPLETER;
+
+        /**
+         * Create a ModuleSymbol with an associated module-info ClassSymbol.
+         * The name of the module may be null, if it is not known yet.
+         */
+        public static ModuleSymbol create(Name name, Name module_info) {
+            ModuleSymbol msym = new ModuleSymbol(name, null);
+            ClassSymbol info = new ClassSymbol(Flags.MODULE, module_info, msym);
+            info.fullname = formFullName(module_info, msym);
+            info.flatname = info.fullname;
+            info.members_field = WriteableScope.create(info);
+            msym.module_info = info;
+            return msym;
+        }
+
+        public ModuleSymbol() {
+            super(MDL, 0, null, null, null);
+            this.type = new ModuleType(this);
+        }
+
+        public ModuleSymbol(Name name, Symbol owner) {
+            super(MDL, 0, name, null, owner);
+            this.type = new ModuleType(this);
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public boolean isUnnamed() {
+            return name.isEmpty() && owner == null;
+        }
+
+        public boolean isNoModule() {
+            return false;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ElementKind getKind() {
+            return ElementKind.MODULE;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public java.util.List<Directive> getDirectives() {
+            completeUsesProvides();
+            return Collections.unmodifiableList(directives);
+        }
+
+        public void completeUsesProvides() {
+            if (usesProvidesCompleter != Completer.NULL_COMPLETER) {
+                Completer c = usesProvidesCompleter;
+                usesProvidesCompleter = Completer.NULL_COMPLETER;
+                c.complete(this);
+            }
+        }
+
+        @Override
+        public ClassSymbol outermostClass() {
+            return null;
+        }
+
+        @Override
+        public String toString() {
+            // TODO: the following strings should be localized
+            // Do this with custom anon subtypes in Symtab
+            String n = (name == null) ? "<unknown>"
+                    : (name.isEmpty()) ? "<unnamed>"
+                    : String.valueOf(name);
+            return n;
+        }
+
+        @Override
+        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+            return v.visitModule(this, p);
+        }
+
+        @Override
+        public List<Symbol> getEnclosedElements() {
+            List<Symbol> list = List.nil();
+            for (Symbol sym : enclosedPackages) {
+                if (sym.members().anyMatch(m -> m.kind == TYP))
+                    list = list.prepend(sym);
+            }
+            return list;
+        }
+
+        public void reset() {
+            this.directives = null;
+            this.requires = null;
+            this.exports = null;
+            this.provides = null;
+            this.uses = null;
+            this.visiblePackages = null;
+        }
+
+    }
 
     /** A class for package symbols
      */
@@ -861,6 +988,7 @@
         public WriteableScope members_field;
         public Name fullname;
         public ClassSymbol package_info; // see bug 6443073
+        public ModuleSymbol modle;
 
         public PackageSymbol(Name name, Type type, Symbol owner) {
             super(PCK, 0, name, type, owner);
@@ -929,7 +1057,7 @@
 
         @DefinedBy(Api.LANGUAGE_MODEL)
         public Symbol getEnclosingElement() {
-            return null;
+            return modle != null && !modle.isNoModule() ? modle : null;
         }
 
         @DefinedBy(Api.LANGUAGE_MODEL)
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
index 68e36be..d0b75a8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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,18 +25,20 @@
 
 package com.sun.tools.javac.code;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import javax.lang.model.element.ElementVisitor;
-import javax.tools.JavaFileObject;
-
 
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
@@ -47,17 +49,18 @@
 import com.sun.tools.javac.code.Type.JCVoidType;
 import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Type.UnknownType;
-import com.sun.tools.javac.jvm.Target;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Convert;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.Iterators;
 import com.sun.tools.javac.util.JavacMessages;
 import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.Options;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -100,17 +103,26 @@
     public final JCVoidType voidType = new JCVoidType();
 
     private final Names names;
+    private final JavacMessages messages;
     private final Completer initialCompleter;
-    private final Target target;
+    private final Completer moduleCompleter;
+
+    /** A symbol for the unnamed module.
+     */
+    public final ModuleSymbol unnamedModule;
+
+    /** The error module.
+     */
+    public final ModuleSymbol errModule;
+
+    /** A symbol for no module, for use with -source 8 or less
+     */
+    public final ModuleSymbol noModule;
 
     /** A symbol for the root package.
      */
     public final PackageSymbol rootPackage;
 
-    /** A symbol for the unnamed package.
-     */
-    public final PackageSymbol unnamedPackage;
-
     /** A symbol that stands for a missing symbol.
      */
     public final TypeSymbol noSymbol;
@@ -139,6 +151,10 @@
     /** The builtin type of all methods. */
     public final ClassSymbol methodClass;
 
+    /** A symbol for the java.base module.
+     */
+    public final ModuleSymbol java_base;
+
     /** Predefined types.
      */
     public final Type objectType;
@@ -208,7 +224,7 @@
      */
     public final Type[] typeOfTag = new Type[TypeTag.getTypeTagCount()];
 
-    /** The name of the class that belongs to a basix type tag.
+    /** The name of the class that belongs to a basic type tag.
      */
     public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()];
 
@@ -217,13 +233,17 @@
      *  It should be updated from the outside to reflect classes defined
      *  by compiled source files.
      */
-    public final Map<Name, ClassSymbol> classes = new HashMap<>();
+    private final Map<Name, Map<ModuleSymbol,ClassSymbol>> classes = new HashMap<>();
 
     /** A hashtable containing the encountered packages.
      *  the table should be updated from outside to reflect packages defined
      *  by compiled source files.
      */
-    public final Map<Name, PackageSymbol> packages = new HashMap<>();
+    private final Map<Name, Map<ModuleSymbol,PackageSymbol>> packages = new HashMap<>();
+
+    /** A hashtable giving the encountered modules.
+     */
+    private final Map<Name, ModuleSymbol> modules = new LinkedHashMap<>();
 
     public void initType(Type type, ClassSymbol c) {
         type.tsym = c;
@@ -239,7 +259,7 @@
 
     public void initType(Type type, String name, String bname) {
         initType(type, name);
-            boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname);
+        boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname);
     }
 
     /** The class symbol that owns all predefined symbols.
@@ -250,12 +270,13 @@
      *  @param s The name of the class.
      */
     private Type enterClass(String s) {
-        return enterClass(names.fromString(s)).type;
+        return enterClass(java_base, names.fromString(s)).type;
     }
 
     public void synthesizeEmptyInterfaceIfMissing(final Type type) {
         final Completer completer = type.tsym.completer;
         type.tsym.completer = new Completer() {
+            @Override
             public void complete(Symbol sym) throws CompletionFailure {
                 try {
                     completer.complete(sym);
@@ -273,9 +294,10 @@
     }
 
     public void synthesizeBoxTypeIfMissing(final Type type) {
-        ClassSymbol sym = enterClass(boxedName[type.getTag().ordinal()]);
+        ClassSymbol sym = enterClass(java_base, boxedName[type.getTag().ordinal()]);
         final Completer completer = sym.completer;
         sym.completer = new Completer() {
+            @Override
             public void complete(Symbol sym) throws CompletionFailure {
                 try {
                     completer.complete(sym);
@@ -308,7 +330,9 @@
     // Enter a synthetic class that is used to mark classes in ct.sym.
     // This class does not have a class file.
     private Type enterSyntheticAnnotation(String name) {
-        ClassType type = (ClassType)enterClass(name);
+        // for now, leave the module null, to prevent problems from synthesizing the
+        // existence of a class in any specific module, including noModule
+        ClassType type = (ClassType)enterClass(java_base, names.fromString(name)).type;
         ClassSymbol sym = (ClassSymbol)type.tsym;
         sym.completer = Completer.NULL_COMPLETER;
         sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
@@ -328,22 +352,35 @@
         context.put(symtabKey, this);
 
         names = Names.instance(context);
-        target = Target.instance(context);
 
         // Create the unknown type
         unknownType = new UnknownType();
 
-        // create the basic builtin symbols
+        messages = JavacMessages.instance(context);
+
         rootPackage = new PackageSymbol(names.empty, null);
-        packages.put(names.empty, rootPackage);
-        final JavacMessages messages = JavacMessages.instance(context);
-        unnamedPackage = new PackageSymbol(names.empty, rootPackage) {
+
+        // create the basic builtin symbols
+        unnamedModule = new ModuleSymbol(names.empty, null) {
+                @Override
                 public String toString() {
-                    return messages.getLocalizedString("compiler.misc.unnamed.package");
+                    return messages.getLocalizedString("compiler.misc.unnamed.module");
                 }
             };
+        addRootPackageFor(unnamedModule);
+
+        errModule = new ModuleSymbol(names.empty, null) { };
+        addRootPackageFor(errModule);
+
+        noModule = new ModuleSymbol(names.empty, null) {
+            @Override public boolean isNoModule() {
+                return true;
+            }
+        };
+        addRootPackageFor(noModule);
+
         noSymbol = new TypeSymbol(NIL, 0, names.empty, Type.noType, rootPackage) {
-            @DefinedBy(Api.LANGUAGE_MODEL)
+            @Override @DefinedBy(Api.LANGUAGE_MODEL)
             public <R, P> R accept(ElementVisitor<R, P> v, P p) {
                 return v.visitUnknown(this, p);
             }
@@ -389,8 +426,7 @@
 
         // Get the initial completer for Symbols from the ClassFinder
         initialCompleter = ClassFinder.instance(context).getCompleter();
-        rootPackage.completer = initialCompleter;
-        unnamedPackage.completer = initialCompleter;
+        rootPackage.members_field = WriteableScope.create(rootPackage);
 
         // Enter symbols for basic types.
         scope.enter(byteType.tsym);
@@ -406,9 +442,22 @@
         // Enter symbol for the errSymbol
         scope.enter(errSymbol);
 
-        classes.put(predefClass.fullname, predefClass);
+        Source source = Source.instance(context);
+        Options options = Options.instance(context);
+        boolean noModules = options.isSet("noModules");
+        if (source.allowModules() && !noModules) {
+            java_base = enterModule(names.java_base);
+            //avoid completing java.base during the Symtab initialization
+            java_base.completer = Completer.NULL_COMPLETER;
+            java_base.visiblePackages = Collections.emptyMap();
+        } else {
+            java_base = noModule;
+        }
 
-        // Enter predefined classes.
+        // Get the initial completer for ModuleSymbols from Modules
+        moduleCompleter = Modules.instance(context).getCompleter();
+
+        // Enter predefined classes. All are assumed to be in the java.base module.
         objectType = enterClass("java.lang.Object");
         objectsType = enterClass("java.util.Objects");
         classType = enterClass("java.lang.Class");
@@ -434,7 +483,7 @@
         cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException");
         annotationType = enterClass("java.lang.annotation.Annotation");
         classLoaderType = enterClass("java.lang.ClassLoader");
-        enumSym = enterClass(names.java_lang_Enum);
+        enumSym = enterClass(java_base, names.java_lang_Enum);
         enumFinalFinalize =
             new MethodSymbol(PROTECTED|FINAL|HYPOTHETICAL,
                              names.finalize,
@@ -512,14 +561,16 @@
                            List.<Type>nil(), methodClass),
             arrayClass);
         arrayClass.members().enter(arrayCloneMethod);
+
+        if (java_base != noModule)
+            java_base.completer = sym -> moduleCompleter.complete(sym); //bootstrap issues
+
     }
 
     /** Define a new class given its name and owner.
      */
     public ClassSymbol defineClass(Name name, Symbol owner) {
         ClassSymbol c = new ClassSymbol(0, name, owner);
-        if (owner.kind == PCK)
-            Assert.checkNull(classes.get(c.flatname), c);
         c.completer = initialCompleter;
         return c;
     }
@@ -527,12 +578,13 @@
     /** Create a new toplevel or member class symbol with given name
      *  and owner and enter in `classes' unless already there.
      */
-    public ClassSymbol enterClass(Name name, TypeSymbol owner) {
+    public ClassSymbol enterClass(ModuleSymbol msym, Name name, TypeSymbol owner) {
+        Assert.checkNonNull(msym);
         Name flatname = TypeSymbol.formFlatName(name, owner);
-        ClassSymbol c = classes.get(flatname);
+        ClassSymbol c = getClass(msym, flatname);
         if (c == null) {
             c = defineClass(name, owner);
-            classes.put(flatname, c);
+            doEnterClass(msym, c);
         } else if ((c.name != name || c.owner != owner) && owner.kind == TYP && c.owner.kind == PCK) {
             // reassign fields of classes that might have been loaded with
             // their flat names.
@@ -544,71 +596,212 @@
         return c;
     }
 
-    /**
-     * Creates a new toplevel class symbol with given flat name and
-     * given class (or source) file.
-     *
-     * @param flatName a fully qualified binary class name
-     * @param classFile the class file or compilation unit defining
-     * the class (may be {@code null})
-     * @return a newly created class symbol
-     * @throws AssertionError if the class symbol already exists
-     */
-    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
-        ClassSymbol cs = classes.get(flatName);
-        if (cs != null) {
-            String msg = Log.format("%s: completer = %s; class file = %s; source file = %s",
-                                    cs.fullname,
-                                    cs.completer,
-                                    cs.classfile,
-                                    cs.sourcefile);
-            throw new AssertionError(msg);
+    public ClassSymbol getClass(ModuleSymbol msym, Name flatName) {
+        Assert.checkNonNull(msym, () -> flatName.toString());
+        return classes.getOrDefault(flatName, Collections.emptyMap()).get(msym);
+    }
+
+    public PackageSymbol lookupPackage(ModuleSymbol msym, Name flatName) {
+        Assert.checkNonNull(msym);
+
+        if (flatName.isEmpty()) {
+            //unnamed packages only from the current module - visiblePackages contains *root* package, not unnamed package!
+            return msym.unnamedPackage;
         }
-        Name packageName = Convert.packagePart(flatName);
-        PackageSymbol owner = packageName.isEmpty()
-                                ? unnamedPackage
-                                : enterPackage(packageName);
-        cs = defineClass(Convert.shortName(flatName), owner);
-        cs.classfile = classFile;
-        classes.put(flatName, cs);
-        return cs;
+
+        if (msym == noModule) {
+            return enterPackage(msym, flatName);
+        }
+
+        msym.complete();
+
+        PackageSymbol pack;
+
+        pack = msym.visiblePackages.get(flatName);
+
+        if (pack != null)
+            return pack;
+
+        pack = getPackage(msym, flatName);
+
+        if (pack != null && pack.exists())
+            return pack;
+
+        boolean dependsOnUnnamed = msym.requires != null &&
+                                   msym.requires.stream()
+                                                .map(rd -> rd.module)
+                                                .anyMatch(mod -> mod == unnamedModule);
+
+        if (dependsOnUnnamed) {
+            //msyms depends on the unnamed module, for which we generally don't know
+            //the list of packages it "exports" ahead of time. So try to lookup the package in the
+            //current module, and in the unnamed module and see if it exists in one of them
+            PackageSymbol unnamedPack = getPackage(unnamedModule, flatName);
+
+            if (unnamedPack != null && unnamedPack.exists()) {
+                msym.visiblePackages.put(unnamedPack.fullname, unnamedPack);
+                return unnamedPack;
+            }
+
+            pack = enterPackage(msym, flatName);
+            pack.complete();
+            if (pack.exists())
+                return pack;
+
+            unnamedPack = enterPackage(unnamedModule, flatName);
+            unnamedPack.complete();
+            if (unnamedPack.exists()) {
+                msym.visiblePackages.put(unnamedPack.fullname, unnamedPack);
+                return unnamedPack;
+            }
+
+            return pack;
+        }
+
+        return enterPackage(msym, flatName);
+    }
+
+    private static final Map<ModuleSymbol, ClassSymbol> EMPTY = new HashMap<>();
+
+    public void removeClass(ModuleSymbol msym, Name flatName) {
+        classes.getOrDefault(flatName, EMPTY).remove(msym);
+    }
+
+    public Iterable<ClassSymbol> getAllClasses() {
+        return () -> Iterators.createCompoundIterator(classes.values(), v -> v.values().iterator());
+    }
+
+    private void doEnterClass(ModuleSymbol msym, ClassSymbol cs) {
+        classes.computeIfAbsent(cs.flatname, n -> new HashMap<>()).put(msym, cs);
     }
 
     /** Create a new member or toplevel class symbol with given flat name
      *  and enter in `classes' unless already there.
      */
-    public ClassSymbol enterClass(Name flatname) {
-        ClassSymbol c = classes.get(flatname);
-        if (c == null)
-            return enterClass(flatname, (JavaFileObject)null);
-        else
+    public ClassSymbol enterClass(ModuleSymbol msym, Name flatname) {
+        Assert.checkNonNull(msym);
+        PackageSymbol ps = lookupPackage(msym, Convert.packagePart(flatname));
+        Assert.checkNonNull(ps);
+        Assert.checkNonNull(ps.modle);
+        ClassSymbol c = getClass(ps.modle, flatname);
+        if (c == null) {
+            c = defineClass(Convert.shortName(flatname), ps);
+            doEnterClass(ps.modle, c);
+            return c;
+        } else
             return c;
     }
 
     /** Check to see if a package exists, given its fully qualified name.
      */
-    public boolean packageExists(Name fullname) {
-        return enterPackage(fullname).exists();
+    public boolean packageExists(ModuleSymbol msym, Name fullname) {
+        Assert.checkNonNull(msym);
+        return enterPackage(msym, fullname).exists();
     }
 
     /** Make a package, given its fully qualified name.
      */
-    public PackageSymbol enterPackage(Name fullname) {
-        PackageSymbol p = packages.get(fullname);
+    public PackageSymbol enterPackage(ModuleSymbol currModule, Name fullname) {
+        Assert.checkNonNull(currModule);
+        PackageSymbol p = getPackage(currModule, fullname);
         if (p == null) {
-            Assert.check(!fullname.isEmpty(), "rootPackage missing!");
+            Assert.check(!fullname.isEmpty(), () -> "rootPackage missing!; currModule: " + currModule);
             p = new PackageSymbol(
-                Convert.shortName(fullname),
-                enterPackage(Convert.packagePart(fullname)));
+                    Convert.shortName(fullname),
+                    enterPackage(currModule, Convert.packagePart(fullname)));
             p.completer = initialCompleter;
-            packages.put(fullname, p);
+            p.modle = currModule;
+            doEnterPackage(currModule, p);
         }
         return p;
     }
 
-    /** Make a package, given its unqualified name and enclosing package.
-     */
-    public PackageSymbol enterPackage(Name name, PackageSymbol owner) {
-        return enterPackage(TypeSymbol.formFullName(name, owner));
+    private void doEnterPackage(ModuleSymbol msym, PackageSymbol pack) {
+        packages.computeIfAbsent(pack.fullname, n -> new HashMap<>()).put(msym, pack);
+        msym.enclosedPackages = msym.enclosedPackages.prepend(pack);
+    }
+
+    private void addRootPackageFor(ModuleSymbol module) {
+        doEnterPackage(module, rootPackage);
+        PackageSymbol unnamedPackage = new PackageSymbol(names.empty, rootPackage) {
+                @Override
+                public String toString() {
+                    return messages.getLocalizedString("compiler.misc.unnamed.package");
+                }
+            };
+        unnamedPackage.modle = module;
+        unnamedPackage.completer = sym -> initialCompleter.complete(sym);
+        module.unnamedPackage = unnamedPackage;
+    }
+
+    public PackageSymbol getPackage(ModuleSymbol module, Name fullname) {
+        return packages.getOrDefault(fullname, Collections.emptyMap()).get(module);
+    }
+
+    public ModuleSymbol enterModule(Name name) {
+        ModuleSymbol msym = modules.get(name);
+        if (msym == null) {
+            msym = ModuleSymbol.create(name, names.module_info);
+            addRootPackageFor(msym);
+            msym.completer = sym -> moduleCompleter.complete(sym); //bootstrap issues
+            modules.put(name, msym);
+        }
+        return msym;
+    }
+
+    public void enterModule(ModuleSymbol msym, Name name) {
+        Assert.checkNull(modules.get(name));
+        Assert.checkNull(msym.name);
+        msym.name = name;
+        addRootPackageFor(msym);
+        ClassSymbol info = msym.module_info;
+        info.fullname = msym.name.append('.', names.module_info);
+        info.flatname = info.fullname;
+        modules.put(name, msym);
+    }
+
+    public ModuleSymbol getModule(Name name) {
+        return modules.get(name);
+    }
+
+    //temporary:
+    public ModuleSymbol inferModule(Name packageName) {
+        if (packageName.isEmpty())
+            return java_base == noModule ? noModule : unnamedModule;//!
+
+        ModuleSymbol msym = null;
+        Map<ModuleSymbol,PackageSymbol> map = packages.get(packageName);
+        if (map == null)
+            return null;
+        for (Map.Entry<ModuleSymbol,PackageSymbol> e: map.entrySet()) {
+            if (!e.getValue().members().isEmpty()) {
+                if (msym == null) {
+                    msym = e.getKey();
+                } else {
+                    return null;
+                }
+            }
+        }
+        return msym;
+    }
+
+    public List<ModuleSymbol> listPackageModules(Name packageName) {
+        if (packageName.isEmpty())
+            return List.nil();
+
+        List<ModuleSymbol> result = List.nil();
+        Map<ModuleSymbol,PackageSymbol> map = packages.get(packageName);
+        if (map != null) {
+            for (Map.Entry<ModuleSymbol, PackageSymbol> e: map.entrySet()) {
+                if (!e.getValue().members().isEmpty()) {
+                    result = result.prepend(e.getKey());
+                }
+            }
+        }
+        return result;
+    }
+
+    public Collection<ModuleSymbol> getAllModules() {
+        return modules.values();
     }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
index 8609c0d..666051f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
@@ -1525,7 +1525,7 @@
 
     public static class PackageType extends Type implements NoType {
 
-        PackageType(TypeSymbol tsym) {
+        PackageType(PackageSymbol tsym) {
             // Package types cannot be annotated
             super(tsym, TypeMetadata.EMPTY);
         }
@@ -1561,6 +1561,49 @@
         }
     }
 
+    public static class ModuleType extends Type implements NoType {
+
+        ModuleType(ModuleSymbol tsym) {
+            // Module types cannot be annotated
+            super(tsym, TypeMetadata.EMPTY);
+        }
+
+        @Override
+        public ModuleType cloneWithMetadata(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a module type");
+        }
+
+        @Override
+        public ModuleType annotatedType(List<Attribute.TypeCompound> annos) {
+            throw new AssertionError("Cannot annotate a module type");
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return TypeTag.MODULE;
+        }
+
+        @Override
+        public <R,S> R accept(Type.Visitor<R,S> v, S s) {
+            return v.visitModuleType(this, s);
+        }
+
+        @Override
+        public String toString() {
+            return tsym.getQualifiedName().toString();
+        }
+
+        @Override
+        public TypeKind getKind() {
+            return TypeKind.MODULE;
+        }
+
+        @Override
+        public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+            return v.visitNoType(this, p);
+        }
+    }
+
     public static class TypeVar extends Type implements TypeVariable {
 
         /** The upper bound of this type variable; set from outside.
@@ -2384,6 +2427,7 @@
         R visitArrayType(ArrayType t, S s);
         R visitMethodType(MethodType t, S s);
         R visitPackageType(PackageType t, S s);
+        R visitModuleType(ModuleType t, S s);
         R visitTypeVar(TypeVar t, S s);
         R visitCapturedType(CapturedType t, S s);
         R visitForAll(ForAll t, S s);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
index 40a0a51..42cdaec 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
@@ -49,6 +49,7 @@
 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Type.ModuleType;
 import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.comp.Attr;
@@ -652,6 +653,11 @@
                 }
 
                 @Override
+                public Type visitModuleType(ModuleType t, List<TypeCompound> s) {
+                    return t.annotatedType(s);
+                }
+
+                @Override
                 public Type visitCapturedType(CapturedType t, List<TypeCompound> s) {
                     return t.annotatedType(s);
                 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
index 418f1e1..e9ea368 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,6 +89,10 @@
      */
     PACKAGE,
 
+    /** The tag of all module "types".
+     */
+    MODULE,
+
     /** The tag of all (source-level) type variables.
      */
     TYPEVAR,
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
index 33029b4..8400fc7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
@@ -3938,7 +3938,7 @@
      * Return the class that boxes the given primitive.
      */
     public ClassSymbol boxedClass(Type t) {
-        return syms.enterClass(syms.boxedName[t.getTag().ordinal()]);
+        return syms.enterClass(syms.java_base, syms.boxedName[t.getTag().ordinal()]);
     }
 
     /**
@@ -3957,7 +3957,7 @@
         for (int i=0; i<syms.boxedName.length; i++) {
             Name box = syms.boxedName[i];
             if (box != null &&
-                asSuper(t, syms.enterClass(box)) != null)
+                asSuper(t, syms.enterClass(syms.java_base, box)) != null)
                 return syms.typeOfTag[i];
         }
         return Type.noType;
@@ -4536,6 +4536,7 @@
         public R visitArrayType(ArrayType t, S s)       { return visitType(t, s); }
         public R visitMethodType(MethodType t, S s)     { return visitType(t, s); }
         public R visitPackageType(PackageType t, S s)   { return visitType(t, s); }
+        public R visitModuleType(ModuleType t, S s)     { return visitType(t, s); }
         public R visitTypeVar(TypeVar t, S s)           { return visitType(t, s); }
         public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); }
         public R visitForAll(ForAll t, S s)             { return visitType(t, s); }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index efa57d8..60c77fc 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -36,6 +36,7 @@
 import com.sun.source.tree.TreeVisitor;
 import com.sun.source.util.SimpleTreeVisitor;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
@@ -60,6 +61,7 @@
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
 import com.sun.tools.javac.util.List;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.ANNOTATION;
 import static com.sun.tools.javac.code.Flags.BLOCK;
@@ -332,7 +334,15 @@
                                            syms.errSymbol.name,
                                            null, null, null, null);
         localEnv.enclClass.sym = syms.errSymbol;
-        return tree.accept(identAttributer, localEnv);
+        return attribIdent(tree, localEnv);
+    }
+
+    /** Attribute a parsed identifier.
+     * @param tree Parsed identifier name
+     * @param env The env to use
+     */
+    public Symbol attribIdent(JCTree tree, Env<AttrContext> env) {
+        return tree.accept(identAttributer, env);
     }
     // where
         private TreeVisitor<Symbol,Env<AttrContext>> identAttributer = new IdentAttributer();
@@ -4238,13 +4248,19 @@
     }
 
     /**
-     * Attribute an env for either a top level tree or class declaration.
+     * Attribute an env for either a top level tree or class or module declaration.
      */
     public void attrib(Env<AttrContext> env) {
-        if (env.tree.hasTag(TOPLEVEL))
-            attribTopLevel(env);
-        else
-            attribClass(env.tree.pos(), env.enclClass.sym);
+        switch (env.tree.getTag()) {
+            case MODULEDEF:
+                attribModule(env.tree.pos(), ((JCModuleDecl)env.tree).sym);
+                break;
+            case TOPLEVEL:
+                attribTopLevel(env);
+                break;
+            default:
+                attribClass(env.tree.pos(), env.enclClass.sym);
+        }
     }
 
     /**
@@ -4260,6 +4276,21 @@
         }
     }
 
+    public void attribModule(DiagnosticPosition pos, ModuleSymbol m) {
+        try {
+            annotate.flush();
+            attribModule(m);
+        } catch (CompletionFailure ex) {
+            chk.completionError(pos, ex);
+        }
+    }
+
+    void attribModule(ModuleSymbol m) {
+        // Get environment current at the point of module definition.
+        Env<AttrContext> env = enter.typeEnvs.get(m);
+        attribStat(env.tree, env);
+    }
+
     /** Main method: attribute class definition associated with given class symbol.
      *  reporting completion failures at the given position.
      *  @param pos The source position at which completion errors are to be
@@ -4358,6 +4389,10 @@
         // nothing to do
     }
 
+    public void visitModuleDef(JCModuleDecl tree) {
+        tree.sym.completeUsesProvides();
+    }
+
     /** Finish the attribution of a class. */
     private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
         JCClassDecl tree = (JCClassDecl)env.tree;
@@ -4929,4 +4964,22 @@
         }
     }
     // </editor-fold>
+
+    public void setPackageSymbols(JCExpression pid, Symbol pkg) {
+        new TreeScanner() {
+            Symbol packge = pkg;
+            @Override
+            public void visitIdent(JCIdent that) {
+                that.sym = packge;
+            }
+
+            @Override
+            public void visitSelect(JCFieldAccess that) {
+                that.sym = packge;
+                packge = packge.owner;
+                super.visitSelect(that);
+            }
+        }.scan(pid);
+    }
+
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index 4b0b3a1..894f73a 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -173,10 +173,10 @@
      */
     char syntheticNameChar;
 
-    /** A table mapping flat names of all compiled classes in this run to their
-     *  symbols; maintained from outside.
+    /** A table mapping flat names of all compiled classes for each module in this run
+     *  to their symbols; maintained from outside.
      */
-    public Map<Name,ClassSymbol> compiled = new HashMap<>();
+    private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
 
     /** A handler for messages about deprecated usage.
      */
@@ -404,7 +404,7 @@
         for (int i = (index == null) ? 1 : index; ; i++) {
             Name flatname = names.fromString(enclFlatnameStr
                     + syntheticNameChar + i + c.name);
-            if (compiled.get(flatname) == null) {
+            if (getCompiled(c.packge().modle, flatname) == null) {
                 localClassNameIndexes.put(key, i + 1);
                 return flatname;
             }
@@ -421,6 +421,22 @@
         localClassNameIndexes.clear();
     }
 
+    public void putCompiled(ClassSymbol csym) {
+        compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym);
+    }
+
+    public ClassSymbol getCompiled(ClassSymbol csym) {
+        return compiled.get(Pair.of(csym.packge().modle, csym.flatname));
+    }
+
+    public ClassSymbol getCompiled(ModuleSymbol msym, Name flatname) {
+        return compiled.get(Pair.of(msym, flatname));
+    }
+
+    public void removeCompiled(ClassSymbol csym) {
+        compiled.remove(Pair.of(csym.packge().modle, csym.flatname));
+    }
+
 /* *************************************************************************
  * Type Checking
  **************************************************************************/
@@ -3473,7 +3489,7 @@
         private boolean isCanonical(JCTree tree) {
             while (tree.hasTag(SELECT)) {
                 JCFieldAccess s = (JCFieldAccess) tree;
-                if (s.sym.owner != TreeInfo.symbol(s.selected))
+                if (s.sym.owner.name != TreeInfo.symbol(s.selected).name)
                     return false;
                 tree = s.selected;
             }
@@ -3576,9 +3592,19 @@
 
     // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2)
     public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) {
-        for (JCImport imp : toplevel.getImports()) {
+        OUTER: for (JCImport imp : toplevel.getImports()) {
             if (!imp.staticImport && TreeInfo.name(imp.qualid) == names.asterisk) {
                 TypeSymbol tsym = ((JCFieldAccess)imp.qualid).selected.type.tsym;
+                if (toplevel.modle.visiblePackages != null) {
+                    //TODO - unclear: selects like javax.* will get resolved from the current module
+                    //(as javax is not an exported package from any module). And as javax in the current
+                    //module typically does not contain any classes or subpackages, we need to go through
+                    //the visible packages to find a sub-package:
+                    for (PackageSymbol known : toplevel.modle.visiblePackages.values()) {
+                        if (Convert.packagePart(known.fullname) == tsym.flatName())
+                            continue OUTER;
+                    }
+                }
                 if (tsym.kind == PCK && tsym.members().isEmpty() && !tsym.exists()) {
                     log.error(DiagnosticFlag.RESOLVE_ERROR, imp.pos, "doesnt.exist", tsym);
                 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
index 6205646..c588ecd 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
@@ -452,17 +452,21 @@
         Log.DeferredDiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator.apply(newTree);
         try {
             attr.attribTree(newTree, speculativeEnv, resultInfo);
-            unenterScanner.scan(newTree);
             return newTree;
         } finally {
-            unenterScanner.scan(newTree);
+            new UnenterScanner(env.toplevel.modle).scan(newTree);
             log.popDiagnosticHandler(deferredDiagnosticHandler);
         }
     }
     //where
-        protected UnenterScanner unenterScanner = new UnenterScanner();
 
         class UnenterScanner extends TreeScanner {
+            private final ModuleSymbol msym;
+
+            public UnenterScanner(ModuleSymbol msym) {
+                this.msym = msym;
+            }
+
             @Override
             public void visitClassDef(JCClassDecl tree) {
                 ClassSymbol csym = tree.sym;
@@ -471,9 +475,9 @@
                 //are left unchecked - in such cases there's nothing to clean up.
                 if (csym == null) return;
                 typeEnvs.remove(csym);
-                chk.compiled.remove(csym.flatname);
+                chk.removeCompiled(csym);
                 chk.clearLocalClassNameIndexes(csym);
-                syms.classes.remove(csym.flatname);
+                syms.removeClass(msym, csym.flatname);
                 super.visitClassDef(tree);
             }
         }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
index fea9983..1fe59e9 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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,6 +25,9 @@
 
 package com.sun.tools.javac.comp;
 
+import java.util.Map;
+import java.util.Optional;
+
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileManager;
 
@@ -34,13 +37,13 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.main.Option.PkgInfo;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 
-
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 
@@ -97,6 +100,8 @@
     JavaFileManager fileManager;
     PkgInfo pkginfoOpt;
     TypeEnvs typeEnvs;
+    Modules modules;
+    JCDiagnostic.Factory diags;
 
     private final Todo todo;
 
@@ -119,6 +124,8 @@
         annotate = Annotate.instance(context);
         lint = Lint.instance(context);
         names = Names.instance(context);
+        modules = Modules.instance(context);
+        diags = JCDiagnostic.Factory.instance(context);
 
         predefClassDef = make.ClassDef(
             make.Modifiers(PUBLIC),
@@ -229,6 +236,24 @@
             : env.info.scope;
     }
 
+    /** Create a fresh environment for modules.
+     *
+     *  @param tree     The module definition.
+     *  @param env      The environment current outside of the module definition.
+     */
+    public Env<AttrContext> moduleEnv(JCModuleDecl tree, Env<AttrContext> env) {
+        Assert.checkNonNull(tree.sym);
+        Env<AttrContext> localEnv =
+            env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
+        localEnv.enclClass = predefClassDef;
+        localEnv.outer = env;
+        localEnv.info.isSelfCall = false;
+        localEnv.info.lint = null; // leave this to be filled in by Attr,
+                                   // when annotations have been processed
+        return localEnv;
+    }
+
+
 /* ************************************************************************
  * Visitor methods for phase 1: class enter
  *************************************************************************/
@@ -276,57 +301,80 @@
 
     @Override
     public void visitTopLevel(JCCompilationUnit tree) {
+//        Assert.checkNonNull(tree.modle, tree.sourcefile.toString());
+
         JavaFileObject prev = log.useSource(tree.sourcefile);
         boolean addEnv = false;
         boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
                                                              JavaFileObject.Kind.SOURCE);
-        JCPackageDecl pd = tree.getPackage();
-        if (pd != null) {
-            tree.packge = pd.packge = syms.enterPackage(TreeInfo.fullName(pd.pid));
-            if (   pd.annotations.nonEmpty()
-                || pkginfoOpt == PkgInfo.ALWAYS
-                || tree.docComments != null) {
-                if (isPkgInfo) {
-                    addEnv = true;
-                } else if (pd.annotations.nonEmpty()) {
-                    log.error(pd.annotations.head.pos(),
-                              "pkg.annotations.sb.in.package-info.java");
-                }
-            }
+        if (TreeInfo.isModuleInfo(tree)) {
+            tree.packge = syms.rootPackage;
+            Env<AttrContext> topEnv = topLevelEnv(tree);
+            classEnter(tree.defs, topEnv);
+            tree.modle.usesProvidesCompleter = modules.getUsesProvidesCompleter();
         } else {
-            tree.packge = syms.unnamedPackage;
-        }
-        tree.packge.complete(); // Find all classes in package.
-        Env<AttrContext> topEnv = topLevelEnv(tree);
-        Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
-
-        // Save environment of package-info.java file.
-        if (isPkgInfo) {
-            Env<AttrContext> env0 = typeEnvs.get(tree.packge);
-            if (env0 != null) {
-                JCCompilationUnit tree0 = env0.toplevel;
-                if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
-                    log.warning(pd != null ? pd.pid.pos() : null,
-                                "pkg-info.already.seen",
-                                tree.packge);
+            JCPackageDecl pd = tree.getPackage();
+            if (pd != null) {
+                tree.packge = pd.packge = syms.enterPackage(tree.modle, TreeInfo.fullName(pd.pid));
+                if (   pd.annotations.nonEmpty()
+                    || pkginfoOpt == PkgInfo.ALWAYS
+                    || tree.docComments != null) {
+                    if (isPkgInfo) {
+                        addEnv = true;
+                    } else if (pd.annotations.nonEmpty()) {
+                        log.error(pd.annotations.head.pos(),
+                                  "pkg.annotations.sb.in.package-info.java");
+                    }
                 }
+            } else {
+                tree.packge = tree.modle.unnamedPackage;
             }
-            typeEnvs.put(tree.packge, packageEnv);
 
-            for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
-                q.flags_field |= EXISTS;
+            Map<Name, PackageSymbol> visiblePackages = tree.modle.visiblePackages;
+            Optional<ModuleSymbol> dependencyWithPackage =
+                syms.listPackageModules(tree.packge.fullname)
+                    .stream()
+                    .filter(m -> m != tree.modle)
+                    .filter(cand -> visiblePackages.get(tree.packge.fullname) == syms.getPackage(cand, tree.packge.fullname))
+                    .findAny();
 
-            Name name = names.package_info;
-            ClassSymbol c = syms.enterClass(name, tree.packge);
-            c.flatname = names.fromString(tree.packge + "." + name);
-            c.sourcefile = tree.sourcefile;
+            if (dependencyWithPackage.isPresent()) {
+                log.error(pd, Errors.PackageInOtherModule(dependencyWithPackage.get()));
+            }
+
+            tree.packge.complete(); // Find all classes in package.
+
+            Env<AttrContext> topEnv = topLevelEnv(tree);
+            Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
+
+            // Save environment of package-info.java file.
+            if (isPkgInfo) {
+                Env<AttrContext> env0 = typeEnvs.get(tree.packge);
+                if (env0 != null) {
+                    JCCompilationUnit tree0 = env0.toplevel;
+                    if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
+                        log.warning(pd != null ? pd.pid.pos() : null,
+                                    "pkg-info.already.seen",
+                                    tree.packge);
+                    }
+                }
+                typeEnvs.put(tree.packge, packageEnv);
+
+                for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
+                    q.flags_field |= EXISTS;
+
+                Name name = names.package_info;
+                ClassSymbol c = syms.enterClass(tree.modle, name, tree.packge);
+                c.flatname = names.fromString(tree.packge + "." + name);
+                c.sourcefile = tree.sourcefile;
             c.completer = Completer.NULL_COMPLETER;
-            c.members_field = WriteableScope.create(c);
-            tree.packge.package_info = c;
-        }
-        classEnter(tree.defs, topEnv);
-        if (addEnv) {
-            todo.append(packageEnv);
+                c.members_field = WriteableScope.create(c);
+                tree.packge.package_info = c;
+            }
+            classEnter(tree.defs, topEnv);
+            if (addEnv) {
+                todo.append(packageEnv);
+            }
         }
         log.useSource(prev);
         result = null;
@@ -342,7 +390,7 @@
             PackageSymbol packge = (PackageSymbol)owner;
             for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
                 q.flags_field |= EXISTS;
-            c = syms.enterClass(tree.name, packge);
+            c = syms.enterClass(env.toplevel.modle, tree.name, packge);
             packge.members().enterIfAbsent(c);
             if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
                 log.error(tree.pos(),
@@ -356,7 +404,7 @@
             }
             if (owner.kind == TYP) {
                 // We are seeing a member class.
-                c = syms.enterClass(tree.name, (TypeSymbol)owner);
+                c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
                 if ((owner.flags_field & INTERFACE) != 0) {
                     tree.mods.flags |= PUBLIC | STATIC;
                 }
@@ -371,13 +419,13 @@
         tree.sym = c;
 
         // Enter class into `compiled' table and enclosing scope.
-        if (chk.compiled.get(c.flatname) != null) {
+        if (chk.getCompiled(c) != null) {
             duplicateClass(tree.pos(), c);
             result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
             tree.sym = (ClassSymbol)result.tsym;
             return;
         }
-        chk.compiled.put(c.flatname, c);
+        chk.putCompiled(c);
         enclScope.enter(c);
 
         // Set up an environment for class block and store in `typeEnvs'
@@ -421,6 +469,8 @@
         // Recursively enter all member classes.
         classEnter(tree.defs, localEnv);
 
+//        Assert.checkNonNull(c.modle, c.sourcefile.toString());
+
         result = c.type;
     }
     //where
@@ -453,6 +503,13 @@
         result = a;
     }
 
+    @Override
+    public void visitModuleDef(JCModuleDecl tree) {
+        Env<AttrContext> moduleEnv = moduleEnv(tree, env);
+        typeEnvs.put(tree.sym, moduleEnv);
+        todo.append(moduleEnv);
+    }
+
     /** Default class enter visitor method: do nothing.
      */
     @Override
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index ad82a1e..776a1bf 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -743,6 +743,10 @@
             }
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -1305,6 +1309,10 @@
             }
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -2416,6 +2424,10 @@
             tree.underlyingType.accept(this);
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -2605,6 +2617,10 @@
             super.visitTry(tree);
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
index 19044bb..197cff5 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
@@ -652,7 +652,7 @@
 
         // Enter class symbol in owner scope and compiled table.
         enterSynthetic(odef.pos(), c, owner.members());
-        chk.compiled.put(c.flatname, c);
+        chk.putCompiled(c);
 
         // Create class definition tree.
         JCClassDecl cdef = make.ClassDef(
@@ -1286,10 +1286,11 @@
      */
     ClassSymbol accessConstructorTag() {
         ClassSymbol topClass = currentClass.outermostClass();
+        ModuleSymbol topModle = topClass.packge().modle;
         Name flatname = names.fromString("" + topClass.getQualifiedName() +
                                          target.syntheticNameChar() +
                                          "1");
-        ClassSymbol ctag = chk.compiled.get(flatname);
+        ClassSymbol ctag = chk.getCompiled(topModle, flatname);
         if (ctag == null)
             ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
         // keep a record of all tags, to verify that all are generated as required
@@ -2342,25 +2343,18 @@
 
     public void visitPackageDef(JCPackageDecl tree) {
         if (!needPackageInfoClass(tree))
-            return;
+                        return;
 
-        Name name = names.package_info;
         long flags = Flags.ABSTRACT | Flags.INTERFACE;
         // package-info is marked SYNTHETIC in JDK 1.6 and later releases
         flags = flags | Flags.SYNTHETIC;
-        JCClassDecl packageAnnotationsClass
-            = make.ClassDef(make.Modifiers(flags, tree.getAnnotations()),
-                            name, List.<JCTypeParameter>nil(),
-                            null, List.<JCExpression>nil(), List.<JCTree>nil());
         ClassSymbol c = tree.packge.package_info;
-        c.flags_field |= flags;
         c.setAttributes(tree.packge);
+        c.flags_field |= flags;
         ClassType ctype = (ClassType) c.type;
         ctype.supertype_field = syms.objectType;
         ctype.interfaces_field = List.nil();
-        packageAnnotationsClass.sym = c;
-
-        translated.append(packageAnnotationsClass);
+        createInfoClass(tree.annotations, c);
     }
     // where
     private boolean needPackageInfoClass(JCPackageDecl pd) {
@@ -2381,6 +2375,23 @@
         throw new AssertionError();
     }
 
+    public void visitModuleDef(JCModuleDecl tree) {
+        ModuleSymbol msym = tree.sym;
+        ClassSymbol c = msym.module_info;
+        c.flags_field |= Flags.MODULE;
+        createInfoClass(List.<JCAnnotation>nil(), tree.sym.module_info);
+    }
+
+    private void createInfoClass(List<JCAnnotation> annots, ClassSymbol c) {
+        long flags = Flags.ABSTRACT | Flags.INTERFACE;
+        JCClassDecl infoClass =
+                make.ClassDef(make.Modifiers(flags, annots),
+                    c.name, List.<JCTypeParameter>nil(),
+                    null, List.<JCExpression>nil(), List.<JCTree>nil());
+        infoClass.sym = c;
+        translated.append(infoClass);
+    }
+
     public void visitClassDef(JCClassDecl tree) {
         Env<AttrContext> prevEnv = attrEnv;
         ClassSymbol currentClassPrev = currentClass;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
new file mode 100644
index 0000000..f25e928
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
@@ -0,0 +1,1243 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package com.sun.tools.javac.comp;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import javax.lang.model.SourceVersion;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Directive;
+import com.sun.tools.javac.code.Directive.ExportsDirective;
+import com.sun.tools.javac.code.Directive.RequiresDirective;
+import com.sun.tools.javac.code.Directive.RequiresFlag;
+import com.sun.tools.javac.code.Directive.UsesDirective;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.ModuleFinder;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.Completer;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.jvm.ClassWriter;
+import com.sun.tools.javac.jvm.JNIWriter;
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCExports;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
+import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
+import com.sun.tools.javac.tree.JCTree.JCProvides;
+import com.sun.tools.javac.tree.JCTree.JCRequires;
+import com.sun.tools.javac.tree.JCTree.JCUses;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.Options;
+
+import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
+import static com.sun.tools.javac.code.Kinds.Kind.MDL;
+import static com.sun.tools.javac.code.TypeTag.CLASS;
+
+import com.sun.tools.javac.tree.JCTree.JCDirective;
+import com.sun.tools.javac.tree.JCTree.Tag;
+
+import static com.sun.tools.javac.code.Flags.ABSTRACT;
+import static com.sun.tools.javac.code.Flags.PUBLIC;
+import static com.sun.tools.javac.tree.JCTree.Tag.MODULEDEF;
+
+/**
+ *  TODO: fill in
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Modules extends JCTree.Visitor {
+    private static final String ALL_SYSTEM = "ALL-SYSTEM";
+    private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
+
+    private final Log log;
+    private final Names names;
+    private final Symtab syms;
+    private final Attr attr;
+    private final TypeEnvs typeEnvs;
+    private final JavaFileManager fileManager;
+    private final ModuleFinder moduleFinder;
+    private final boolean allowModules;
+
+    public final boolean multiModuleMode;
+    public final boolean noModules;
+
+    private final String moduleOverride;
+
+    ModuleSymbol defaultModule;
+
+    private final String addExportsOpt;
+    private Map<ModuleSymbol, Set<ExportsDirective>> addExports;
+    private final String addReadsOpt;
+    private Map<ModuleSymbol, Set<RequiresDirective>> addReads;
+    private final String addModsOpt;
+    private final String limitModsOpt;
+
+    private Set<ModuleSymbol> rootModules = Collections.emptySet();
+
+    public static Modules instance(Context context) {
+        Modules instance = context.get(Modules.class);
+        if (instance == null)
+            instance = new Modules(context);
+        return instance;
+    }
+
+    protected Modules(Context context) {
+        context.put(Modules.class, this);
+        log = Log.instance(context);
+        names = Names.instance(context);
+        syms = Symtab.instance(context);
+        attr = Attr.instance(context);
+        typeEnvs = TypeEnvs.instance(context);
+        moduleFinder = ModuleFinder.instance(context);
+        fileManager = context.get(JavaFileManager.class);
+        allowModules = Source.instance(context).allowModules();
+        Options options = Options.instance(context);
+
+        moduleOverride = options.get(Option.XMODULE);
+
+        // The following is required, for now, to support building
+        // Swing beaninfo via javadoc.
+        noModules = options.isSet("noModules");
+
+        multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
+        ClassWriter classWriter = ClassWriter.instance(context);
+        classWriter.multiModuleMode = multiModuleMode;
+        JNIWriter jniWriter = JNIWriter.instance(context);
+        jniWriter.multiModuleMode = multiModuleMode;
+
+        addExportsOpt = options.get(Option.XADDEXPORTS);
+        addReadsOpt = options.get(Option.XADDREADS);
+        addModsOpt = options.get(Option.ADDMODS);
+        limitModsOpt = options.get(Option.LIMITMODS);
+    }
+
+    int depth = -1;
+    private void dprintln(String msg) {
+        for (int i = 0; i < depth; i++)
+            System.err.print("  ");
+        System.err.println(msg);
+    }
+
+    public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) {
+        if (!allowModules || noModules) {
+            for (JCCompilationUnit tree: trees) {
+                tree.modle = syms.noModule;
+            }
+            defaultModule = syms.noModule;
+            return true;
+        }
+
+        int startErrors = log.nerrors;
+
+        depth++;
+        try {
+            // scan trees for module defs
+            Set<ModuleSymbol> roots = enterModules(trees, c);
+
+            setCompilationUnitModules(trees, roots);
+
+            if (!roots.isEmpty() && this.rootModules.isEmpty()) {
+                this.rootModules = roots;
+                allModules(); //ensure errors reported
+            }
+
+            for (ModuleSymbol msym: roots) {
+                msym.complete();
+            }
+        } finally {
+            depth--;
+        }
+
+        return (log.nerrors == startErrors);
+    }
+
+    public Completer getCompleter() {
+        return mainCompleter;
+    }
+
+    public ModuleSymbol getDefaultModule() {
+        return defaultModule;
+    }
+
+    private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) {
+        Set<ModuleSymbol> modules = new LinkedHashSet<>();
+        for (JCCompilationUnit tree : trees) {
+            JavaFileObject prev = log.useSource(tree.sourcefile);
+            try {
+                enterModule(tree, c, modules);
+            } finally {
+                log.useSource(prev);
+            }
+        }
+        return modules;
+    }
+
+
+    private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set<ModuleSymbol> modules) {
+        boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
+        boolean isModuleDecl = toplevel.defs.nonEmpty() && toplevel.defs.head.hasTag(MODULEDEF);
+        if (isModuleInfo && isModuleDecl) {
+            JCModuleDecl decl = (JCModuleDecl) toplevel.defs.head;
+            Name name = TreeInfo.fullName(decl.qualId);
+            ModuleSymbol sym;
+            if (c != null) {
+               sym = (ModuleSymbol) c.owner;
+               if (sym.name == null) {
+                   //ModuleFinder.findSingleModule creates a stub of a ModuleSymbol without a name,
+                   //fill the name here after the module-info.java has been parsed
+                   //also enter the ModuleSymbol among modules:
+                   syms.enterModule(sym, name);
+               } else {
+                   // TODO: validate name
+               }
+            } else {
+                sym = syms.enterModule(name);
+                if (sym.module_info.sourcefile != null && sym.module_info.sourcefile != toplevel.sourcefile) {
+                    log.error(decl.pos(), Errors.DuplicateModule(sym));
+                    return;
+                }
+            }
+            sym.completer = getSourceCompleter(toplevel);
+            sym.module_info.sourcefile = toplevel.sourcefile;
+            decl.sym = sym;
+
+            if (multiModuleMode || modules.isEmpty()) {
+                modules.add(sym);
+            } else {
+                log.error(toplevel.pos(), Errors.TooManyModules);
+            }
+
+            Env<AttrContext> provisionalEnv = new Env<>(decl, null);
+
+            provisionalEnv.toplevel = toplevel;
+            typeEnvs.put(sym, provisionalEnv);
+        } else if (isModuleInfo) {
+            if (multiModuleMode) {
+                JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head;
+                log.error(tree.pos(), Errors.ExpectedModule);
+            }
+        } else if (isModuleDecl) {
+            JCTree tree = toplevel.defs.head;
+            log.error(tree.pos(), Errors.ModuleDeclSbInModuleInfoJava);
+        }
+    }
+
+    private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules) {
+        // update the module for each compilation unit
+        if (multiModuleMode) {
+            checkNoAllModulePath();
+            for (JCCompilationUnit tree: trees) {
+                if (tree.defs.isEmpty()) {
+                    tree.modle = syms.unnamedModule;
+                    continue;
+                }
+
+                JavaFileObject prev = log.useSource(tree.sourcefile);
+                try {
+                    Location locn = getModuleLocation(tree);
+                    if (locn != null) {
+                        Name name = names.fromString(fileManager.inferModuleName(locn));
+                        ModuleSymbol msym;
+                        if (tree.defs.head.hasTag(MODULEDEF)) {
+                            JCModuleDecl decl = (JCModuleDecl) tree.defs.head;
+                            msym = decl.sym;
+                            if (msym.name != name) {
+                                log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
+                            }
+                        } else {
+                            msym = syms.enterModule(name);
+                        }
+                        if (msym.sourceLocation == null) {
+                            msym.sourceLocation = locn;
+                            if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                                msym.classLocation = fileManager.getModuleLocation(
+                                        StandardLocation.CLASS_OUTPUT, msym.name.toString());
+                            }
+                        }
+                        tree.modle = msym;
+                        rootModules.add(msym);
+                    } else {
+                        log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules);
+                        tree.modle = syms.errModule;
+                    }
+                } catch (IOException e) {
+                    throw new Error(e); // FIXME
+                } finally {
+                    log.useSource(prev);
+                }
+            }
+            if (syms.unnamedModule.sourceLocation == null) {
+                syms.unnamedModule.completer = getUnnamedModuleCompleter();
+                syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
+            }
+            defaultModule = syms.unnamedModule;
+        } else {
+            if (defaultModule == null) {
+                switch (rootModules.size()) {
+                    case 0:
+                        defaultModule = moduleFinder.findSingleModule();
+                        if (defaultModule == syms.unnamedModule) {
+                            if (moduleOverride != null) {
+                                checkNoAllModulePath();
+                                defaultModule = moduleFinder.findModule(names.fromString(moduleOverride));
+                            } else {
+                                // Question: why not do findAllModules and initVisiblePackages here?
+                                // i.e. body of unnamedModuleCompleter
+                                defaultModule.completer = getUnnamedModuleCompleter();
+                                defaultModule.classLocation = StandardLocation.CLASS_PATH;
+                            }
+                        } else {
+                            checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleClasspath);
+                            checkNoAllModulePath();
+                            defaultModule.complete();
+                            // Question: why not do completeModule here?
+                            defaultModule.completer = new Completer() {
+                                @Override
+                                public void complete(Symbol sym) throws CompletionFailure {
+                                    completeModule((ModuleSymbol) sym);
+                                }
+                            };
+                        }
+                        rootModules.add(defaultModule);
+                        break;
+                    case 1:
+                        checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleSourcepath);
+                        checkNoAllModulePath();
+                        defaultModule = rootModules.iterator().next();
+                        defaultModule.classLocation = StandardLocation.CLASS_OUTPUT;
+                        break;
+                    default:
+                        Assert.error("too many modules");
+                }
+                defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
+            } else if (rootModules.size() == 1 && defaultModule == rootModules.iterator().next()) {
+                defaultModule.complete();
+                defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
+            } else {
+                Assert.check(rootModules.isEmpty());
+            }
+
+            if (defaultModule != syms.unnamedModule) {
+                syms.unnamedModule.completer = getUnnamedModuleCompleter();
+                syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
+            }
+
+            for (JCCompilationUnit tree: trees) {
+                tree.modle = defaultModule;
+            }
+        }
+    }
+
+    private Location getModuleLocation(JCCompilationUnit tree) throws IOException {
+        switch (tree.defs.head.getTag()) {
+            case MODULEDEF:
+                return getModuleLocation(tree.sourcefile, null);
+
+            case PACKAGEDEF:
+                JCPackageDecl pkg = (JCPackageDecl) tree.defs.head;
+                return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid));
+
+            default:
+                // code in unnamed module
+                return null;
+        }
+    }
+
+    private Location getModuleLocation(JavaFileObject fo, Name pkgName) throws IOException {
+        // For now, just check module source path.
+        // We may want to check source path as well.
+        return fileManager.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH,
+                fo, (pkgName == null) ? null : pkgName.toString());
+    }
+
+    private void checkSpecifiedModule(List<JCCompilationUnit> trees, JCDiagnostic.Error error) {
+        if (moduleOverride != null) {
+            JavaFileObject prev = log.useSource(trees.head.sourcefile);
+            try {
+                log.error(trees.head.pos(), error);
+            } finally {
+                log.useSource(prev);
+            }
+        }
+    }
+
+    private void checkNoAllModulePath() {
+        if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) {
+            log.error(Errors.AddmodsAllModulePathInvalid);
+        }
+    }
+
+    private final Completer mainCompleter = new Completer() {
+        @Override
+        public void complete(Symbol sym) throws CompletionFailure {
+            ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
+
+            if (msym.kind == Kinds.Kind.ERR) {
+                log.error(Errors.CantFindModule(msym));
+                //make sure the module is initialized:
+                msym.directives = List.nil();
+                msym.exports = List.nil();
+                msym.provides = List.nil();
+                msym.requires = List.nil();
+                msym.uses = List.nil();
+            } else if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) {
+                completeAutomaticModule(msym);
+            } else {
+                msym.module_info.complete();
+            }
+
+            // If module-info comes from a .java file, the underlying
+            // call of classFinder.fillIn will have called through the
+            // source completer, to Enter, and then to Modules.enter,
+            // which will call completeModule.
+            // But, if module-info comes from a .class file, the underlying
+            // call of classFinder.fillIn will just call ClassReader to read
+            // the .class file, and so we call completeModule here.
+            if (msym.module_info.classfile == null || msym.module_info.classfile.getKind() == Kind.CLASS) {
+                completeModule(msym);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "mainCompleter";
+        }
+    };
+
+    private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
+        try {
+            ListBuffer<Directive> directives = new ListBuffer<>();
+            ListBuffer<ExportsDirective> exports = new ListBuffer<>();
+            Set<String> seenPackages = new HashSet<>();
+
+            for (JavaFileObject clazz : fileManager.list(msym.classLocation, "", EnumSet.of(Kind.CLASS), true)) {
+                String binName = fileManager.inferBinaryName(msym.classLocation, clazz);
+                String pack = binName.lastIndexOf('.') != (-1) ? binName.substring(0, binName.lastIndexOf('.')) : ""; //unnamed package????
+                if (seenPackages.add(pack)) {
+                    ExportsDirective d = new ExportsDirective(syms.enterPackage(msym, names.fromString(pack)), null);
+                    directives.add(d);
+                    exports.add(d);
+                }
+            }
+
+            ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+
+            //ensure all modules are found:
+            moduleFinder.findAllModules();
+
+            for (ModuleSymbol ms : allModules()) {
+                if (ms == syms.unnamedModule || ms == msym)
+                    continue;
+                RequiresDirective d = new RequiresDirective(ms, EnumSet.of(RequiresFlag.PUBLIC));
+                directives.add(d);
+                requires.add(d);
+            }
+
+            RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
+            directives.add(requiresUnnamed);
+            requires.add(requiresUnnamed);
+
+            msym.exports = exports.toList();
+            msym.provides = List.nil();
+            msym.requires = requires.toList();
+            msym.uses = List.nil();
+            msym.directives = directives.toList();
+            msym.flags_field |= Flags.ACYCLIC;
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private Completer getSourceCompleter(JCCompilationUnit tree) {
+        return new Completer() {
+            @Override
+            public void complete(Symbol sym) throws CompletionFailure {
+                ModuleSymbol msym = (ModuleSymbol) sym;
+                msym.flags_field |= UNATTRIBUTED;
+                ModuleVisitor v = new ModuleVisitor();
+                JavaFileObject prev = log.useSource(tree.sourcefile);
+                try {
+                    tree.defs.head.accept(v);
+                    completeModule(msym);
+                    checkCyclicDependencies((JCModuleDecl) tree.defs.head);
+                } finally {
+                    log.useSource(prev);
+                    msym.flags_field &= ~UNATTRIBUTED;
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "SourceCompleter: " + tree.sourcefile.getName();
+            }
+
+        };
+    }
+
+    class ModuleVisitor extends JCTree.Visitor {
+        private ModuleSymbol sym;
+        private final Set<ModuleSymbol> allRequires = new HashSet<>();
+        private final Set<PackageSymbol> allExports = new HashSet<>();
+
+        @Override
+        public void visitModuleDef(JCModuleDecl tree) {
+            sym = Assert.checkNonNull(tree.sym);
+
+            sym.requires = List.nil();
+            sym.exports = List.nil();
+            tree.directives.forEach(t -> t.accept(this));
+            sym.requires = sym.requires.reverse();
+            sym.exports = sym.exports.reverse();
+            ensureJavaBase();
+        }
+
+        @Override
+        public void visitRequires(JCRequires tree) {
+            ModuleSymbol msym = lookupModule(tree.moduleName);
+            if (msym.kind != MDL) {
+                log.error(tree.moduleName.pos(), Errors.ModuleNotFound(msym));
+            } else if (allRequires.contains(msym)) {
+                log.error(tree.moduleName.pos(), Errors.DuplicateRequires(msym));
+            } else {
+                allRequires.add(msym);
+                Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class);
+                if (tree.isPublic)
+                    flags.add(RequiresFlag.PUBLIC);
+                RequiresDirective d = new RequiresDirective(msym, flags);
+                tree.directive = d;
+                sym.requires = sym.requires.prepend(d);
+            }
+        }
+
+        @Override
+        public void visitExports(JCExports tree) {
+            Name name = TreeInfo.fullName(tree.qualid);
+            PackageSymbol packge = syms.enterPackage(sym, name);
+            attr.setPackageSymbols(tree.qualid, packge);
+            if (!allExports.add(packge)) {
+                log.error(tree.qualid.pos(), Errors.DuplicateExports(packge));
+            }
+
+            List<ModuleSymbol> toModules = null;
+            if (tree.moduleNames != null) {
+                Set<ModuleSymbol> to = new HashSet<>();
+                for (JCExpression n: tree.moduleNames) {
+                    ModuleSymbol msym = lookupModule(n);
+                    if (msym.kind != MDL) {
+                        log.error(n.pos(), Errors.ModuleNotFound(msym));
+                    } else if (!to.add(msym)) {
+                        log.error(n.pos(), Errors.DuplicateExports(msym));
+                    }
+                }
+                toModules = List.from(to);
+            }
+
+            if (toModules == null || !toModules.isEmpty()) {
+                ExportsDirective d = new ExportsDirective(packge, toModules);
+                tree.directive = d;
+                sym.exports = sym.exports.prepend(d);
+            }
+        }
+
+        @Override
+        public void visitProvides(JCProvides tree) { }
+
+        @Override
+        public void visitUses(JCUses tree) { }
+
+        private void ensureJavaBase() {
+            if (sym.name == names.java_base)
+                return;
+
+            for (RequiresDirective d: sym.requires) {
+                if (d.module.name == names.java_base)
+                    return;
+            }
+
+            ModuleSymbol java_base = syms.enterModule(names.java_base);
+            Directive.RequiresDirective d =
+                    new Directive.RequiresDirective(java_base,
+                            EnumSet.of(Directive.RequiresFlag.MANDATED));
+            sym.requires = sym.requires.prepend(d);
+        }
+
+        private ModuleSymbol lookupModule(JCExpression moduleName) {
+            try {
+            Name name = TreeInfo.fullName(moduleName);
+            ModuleSymbol msym = moduleFinder.findModule(name);
+            TreeInfo.setSymbol(moduleName, msym);
+            return msym;
+            } catch (Throwable t) {
+                System.err.println("Module " + sym + "; lookup export " + moduleName);
+                throw t;
+            }
+        }
+    }
+
+    public Completer getUsesProvidesCompleter() {
+        return sym -> {
+            ModuleSymbol msym = (ModuleSymbol) sym;
+            Env<AttrContext> env = typeEnvs.get(msym);
+            UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
+            JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
+            try {
+                env.toplevel.defs.head.accept(v);
+            } finally {
+                log.useSource(prev);
+            }
+        };
+    }
+
+    class UsesProvidesVisitor extends JCTree.Visitor {
+        private final ModuleSymbol msym;
+        private final Env<AttrContext> env;
+
+        private final Set<Directive.UsesDirective> allUses = new HashSet<>();
+        private final Set<Directive.ProvidesDirective> allProvides = new HashSet<>();
+
+        public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) {
+            this.msym = msym;
+            this.env = env;
+        }
+
+        @Override @SuppressWarnings("unchecked")
+        public void visitModuleDef(JCModuleDecl tree) {
+            msym.directives = List.nil();
+            msym.provides = List.nil();
+            msym.uses = List.nil();
+            tree.directives.forEach(t -> t.accept(this));
+            msym.directives = msym.directives.reverse();
+            msym.provides = msym.provides.reverse();
+            msym.uses = msym.uses.reverse();
+
+            if (msym.requires.nonEmpty() && msym.requires.head.flags.contains(RequiresFlag.MANDATED))
+                msym.directives = msym.directives.prepend(msym.requires.head);
+
+            msym.directives = msym.directives.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet())));
+
+            checkForCorrectness();
+        }
+
+        @Override
+        public void visitExports(JCExports tree) {
+            if (tree.directive.packge.members().isEmpty()) {
+                log.error(tree.qualid.pos(), Errors.PackageEmptyOrNotFound(tree.directive.packge));
+            }
+            msym.directives = msym.directives.prepend(tree.directive);
+        }
+
+        MethodSymbol noArgsConstructor(ClassSymbol tsym) {
+            for (Symbol sym : tsym.members().getSymbolsByName(names.init)) {
+                MethodSymbol mSym = (MethodSymbol)sym;
+                if (mSym.params().isEmpty()) {
+                    return mSym;
+                }
+            }
+            return null;
+        }
+
+        Map<Directive.ProvidesDirective, JCProvides> directiveToTreeMap = new HashMap<>();
+
+        @Override
+        public void visitProvides(JCProvides tree) {
+            Type st = attr.attribType(tree.serviceName, env, syms.objectType);
+            Type it = attr.attribType(tree.implName, env, st);
+            ClassSymbol service = (ClassSymbol) st.tsym;
+            ClassSymbol impl = (ClassSymbol) it.tsym;
+            if ((impl.flags() & ABSTRACT) != 0) {
+                log.error(tree.implName.pos(), Errors.ServiceImplementationIsAbstract(impl));
+            } else if (impl.isInner()) {
+                log.error(tree.implName.pos(), Errors.ServiceImplementationIsInner(impl));
+            } else if (service.isInner()) {
+                log.error(tree.serviceName.pos(), Errors.ServiceDefinitionIsInner(service));
+            } else {
+                MethodSymbol constr = noArgsConstructor(impl);
+                if (constr == null) {
+                    log.error(tree.implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl));
+                } else if ((constr.flags() & PUBLIC) == 0) {
+                    log.error(tree.implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl));
+                }
+            }
+            if (st.hasTag(CLASS) && it.hasTag(CLASS)) {
+                Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impl);
+                if (!allProvides.add(d)) {
+                    log.error(tree.pos(), Errors.DuplicateProvides(service, impl));
+                }
+                msym.provides = msym.provides.prepend(d);
+                msym.directives = msym.directives.prepend(d);
+                directiveToTreeMap.put(d, tree);
+            }
+        }
+
+        @Override
+        public void visitRequires(JCRequires tree) {
+            msym.directives = msym.directives.prepend(tree.directive);
+        }
+
+        @Override
+        public void visitUses(JCUses tree) {
+            Type st = attr.attribType(tree.qualid, env, syms.objectType);
+            if (st.hasTag(CLASS)) {
+                ClassSymbol service = (ClassSymbol) st.tsym;
+                Directive.UsesDirective d = new Directive.UsesDirective(service);
+                if (!allUses.add(d)) {
+                    log.error(tree.pos(), Errors.DuplicateUses(service));
+                }
+                msym.uses = msym.uses.prepend(d);
+                msym.directives = msym.directives.prepend(d);
+            }
+        }
+
+        private void checkForCorrectness() {
+            for (Directive.ProvidesDirective provides : allProvides) {
+                JCProvides tree = directiveToTreeMap.get(provides);
+                /** The implementation must be defined in the same module as the provides directive
+                 *  (else, error)
+                 */
+                PackageSymbol implementationDefiningPackage = provides.impl.packge();
+                if (implementationDefiningPackage.modle != msym) {
+                    log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle));
+                }
+
+                /** There is no inherent requirement that module that provides a service should actually
+                 *  use it itself. However, it is a pointless declaration if the service package is not
+                 *  exported and there is no uses for the service.
+                 */
+                PackageSymbol interfaceDeclaringPackage = provides.service.packge();
+                boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym;
+                boolean isInterfaceExportedFromAReadableModule =
+                        msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage;
+                if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) {
+                    // ok the interface is declared in this module. Let's check if it's exported
+                    boolean warn = true;
+                    for (ExportsDirective export : msym.exports) {
+                        if (interfaceDeclaringPackage == export.packge) {
+                            warn = false;
+                            break;
+                        }
+                    }
+                    if (warn) {
+                        for (UsesDirective uses : msym.uses) {
+                            if (provides.service == uses.service) {
+                                warn = false;
+                                break;
+                            }
+                        }
+                    }
+                    if (warn) {
+                        log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service));
+                    }
+                }
+            }
+        }
+    }
+
+    private Set<ModuleSymbol> allModulesCache;
+
+    private Set<ModuleSymbol> allModules() {
+        if (allModulesCache != null)
+            return allModulesCache;
+
+        Set<ModuleSymbol> observable;
+
+        if (limitModsOpt == null) {
+            observable = null;
+        } else {
+            Set<ModuleSymbol> limitMods = new HashSet<>();
+            for (String limit : limitModsOpt.split(",")) {
+                limitMods.add(syms.enterModule(names.fromString(limit)));
+            }
+            observable = computeTransitiveClosure(limitMods, null);
+            observable.addAll(rootModules);
+        }
+
+        Predicate<ModuleSymbol> observablePred = sym -> observable == null || observable.contains(sym);
+        Predicate<ModuleSymbol> systemModulePred = sym -> (sym.flags() & Flags.SYSTEM_MODULE) != 0;
+        Set<ModuleSymbol> enabledRoot = new LinkedHashSet<>();
+
+        if (rootModules.contains(syms.unnamedModule)) {
+            for (ModuleSymbol sym : syms.getAllModules()) {
+                if (systemModulePred.test(sym) && observablePred.test(sym)) {
+                    enabledRoot.add(sym);
+                }
+            }
+        }
+
+        enabledRoot.addAll(rootModules);
+
+        if (addModsOpt != null) {
+            for (String added : addModsOpt.split(",")) {
+                Stream<ModuleSymbol> modules;
+                switch (added) {
+                    case ALL_SYSTEM:
+                        modules = syms.getAllModules()
+                                      .stream()
+                                      .filter(systemModulePred.and(observablePred));
+                        break;
+                    case ALL_MODULE_PATH:
+                        modules = syms.getAllModules()
+                                      .stream()
+                                      .filter(systemModulePred.negate().and(observablePred));
+                        break;
+                    default:
+                        modules = Stream.of(syms.enterModule(names.fromString(added)));
+                        break;
+                }
+                modules.forEach(sym -> {
+                    enabledRoot.add(sym);
+                    if (observable != null)
+                        observable.add(sym);
+                });
+            }
+        }
+
+        Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable);
+
+        result.add(syms.unnamedModule);
+
+        if (!rootModules.isEmpty())
+            allModulesCache = result;
+
+        return result;
+    }
+
+    public void enableAllModules() {
+        allModulesCache = new HashSet<>();
+
+        moduleFinder.findAllModules();
+
+        for (ModuleSymbol msym : syms.getAllModules()) {
+            allModulesCache.add(msym);
+        }
+    }
+
+    private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
+        List<ModuleSymbol> todo = List.nil();
+
+        for (ModuleSymbol ms : base) {
+            todo = todo.prepend(ms);
+        }
+
+        Set<ModuleSymbol> result = new LinkedHashSet<>();
+        result.add(syms.java_base);
+
+        while (todo.nonEmpty()) {
+            ModuleSymbol current = todo.head;
+            todo = todo.tail;
+            if (observable != null && !observable.contains(current))
+                continue;
+            if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0))
+                continue;
+            current.complete();
+            for (RequiresDirective rd : current.requires) {
+                todo = todo.prepend(rd.module);
+            }
+        }
+
+        return result;
+    }
+
+    public ModuleSymbol getObservableModule(Name name) {
+        ModuleSymbol mod = syms.getModule(name);
+
+        if (allModules().contains(mod)) {
+            return mod;
+        }
+
+        return null;
+    }
+
+    private Completer getUnnamedModuleCompleter() {
+        moduleFinder.findAllModules();
+        return new Symbol.Completer() {
+            @Override
+            public void complete(Symbol sym) throws CompletionFailure {
+                ModuleSymbol msym = (ModuleSymbol) sym;
+                Set<ModuleSymbol> allModules = allModules();
+                for (ModuleSymbol m : allModules) {
+                    m.complete();
+                }
+                initVisiblePackages(msym, allModules);
+            }
+
+            @Override
+            public String toString() {
+                return "unnamedModule Completer";
+            }
+        };
+    }
+
+    private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>();
+
+    private void completeModule(ModuleSymbol msym) {
+        Assert.checkNonNull(msym.requires);
+
+        initAddReads();
+
+        msym.requires = msym.requires.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet())));
+
+        List<RequiresDirective> requires = msym.requires;
+        List<RequiresDirective> previous = null;
+
+        while (requires.nonEmpty()) {
+            if (!allModules().contains(requires.head.module)) {
+                Env<AttrContext> env = typeEnvs.get(msym);
+                if (env != null) {
+                    JavaFileObject origSource = log.useSource(env.toplevel.sourcefile);
+                    try {
+                        log.error(/*XXX*/env.tree, Errors.ModuleNotFound(requires.head.module));
+                    } finally {
+                        log.useSource(origSource);
+                    }
+                } else {
+                    Assert.check((msym.flags() & Flags.AUTOMATIC_MODULE) == 0);
+                }
+                if (previous != null) {
+                    previous.tail = requires.tail;
+                } else {
+                    msym.requires.tail = requires.tail;
+                }
+            } else {
+                previous = requires;
+            }
+            requires = requires.tail;
+        }
+
+        Set<ModuleSymbol> readable = new LinkedHashSet<>();
+        Set<ModuleSymbol> requiresPublic = new HashSet<>();
+        if ((msym.flags() & Flags.AUTOMATIC_MODULE) == 0) {
+            for (RequiresDirective d : msym.requires) {
+                d.module.complete();
+                readable.add(d.module);
+                Set<ModuleSymbol> s = retrieveRequiresPublic(d.module);
+                Assert.checkNonNull(s, () -> "no entry in cache for " + d.module);
+                readable.addAll(s);
+                if (d.flags.contains(RequiresFlag.PUBLIC)) {
+                    requiresPublic.add(d.module);
+                    requiresPublic.addAll(s);
+                }
+            }
+        } else {
+            //the module graph may contain cycles involving automatic modules
+            //handle automatic modules separatelly:
+            Set<ModuleSymbol> s = retrieveRequiresPublic(msym);
+
+            readable.addAll(s);
+            requiresPublic.addAll(s);
+
+            //ensure the unnamed module is added (it is not requires public):
+            readable.add(syms.unnamedModule);
+        }
+        requiresPublicCache.put(msym, requiresPublic);
+        initVisiblePackages(msym, readable);
+        for (ExportsDirective d: msym.exports) {
+            d.packge.modle = msym;
+        }
+
+    }
+
+    private Set<ModuleSymbol> retrieveRequiresPublic(ModuleSymbol msym) {
+        Set<ModuleSymbol> requiresPublic = requiresPublicCache.get(msym);
+
+        if (requiresPublic == null) {
+            //the module graph may contain cycles involving automatic modules or -XaddReads edges
+            requiresPublic = new HashSet<>();
+
+            Set<ModuleSymbol> seen = new HashSet<>();
+            List<ModuleSymbol> todo = List.of(msym);
+
+            while (todo.nonEmpty()) {
+                ModuleSymbol current = todo.head;
+                todo = todo.tail;
+                if (!seen.add(current))
+                    continue;
+                requiresPublic.add(current);
+                current.complete();
+                Iterable<? extends RequiresDirective> requires;
+                if (current != syms.unnamedModule) {
+                    Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym);
+                    requires = current.requires;
+                    for (RequiresDirective rd : requires) {
+                        if (rd.isPublic())
+                            todo = todo.prepend(rd.module);
+                    }
+                } else {
+                    for (ModuleSymbol mod : allModules()) {
+                        todo = todo.prepend(mod);
+                    }
+                }
+            }
+
+            requiresPublic.remove(msym);
+        }
+
+        return requiresPublic;
+    }
+
+    private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) {
+        initAddExports();
+
+        msym.visiblePackages = new LinkedHashMap<>();
+
+        Map<Name, ModuleSymbol> seen = new HashMap<>();
+
+        for (ModuleSymbol rm : readable) {
+            if (rm == syms.unnamedModule)
+                continue;
+            addVisiblePackages(msym, seen, rm, rm.exports);
+        }
+
+        for (Entry<ModuleSymbol, Set<ExportsDirective>> addExportsEntry : addExports.entrySet())
+            addVisiblePackages(msym, seen, addExportsEntry.getKey(), addExportsEntry.getValue());
+    }
+
+    private void addVisiblePackages(ModuleSymbol msym,
+                                    Map<Name, ModuleSymbol> seenPackages,
+                                    ModuleSymbol exportsFrom,
+                                    Collection<ExportsDirective> exports) {
+        for (ExportsDirective d : exports) {
+            if (d.modules == null || d.modules.contains(msym)) {
+                Name packageName = d.packge.fullname;
+                ModuleSymbol previousModule = seenPackages.get(packageName);
+
+                if (previousModule != null && previousModule != exportsFrom) {
+                    Env<AttrContext> env = typeEnvs.get(msym);
+                    JavaFileObject origSource = env != null ? log.useSource(env.toplevel.sourcefile)
+                                                            : null;
+                    DiagnosticPosition pos = env != null ? env.tree.pos() : null;
+                    try {
+                        log.error(pos, Errors.PackageClashFromRequires(msym, packageName,
+                                                                      previousModule, exportsFrom));
+                    } finally {
+                        if (env != null)
+                            log.useSource(origSource);
+                    }
+                    continue;
+                }
+
+                seenPackages.put(packageName, exportsFrom);
+                msym.visiblePackages.put(d.packge.fullname, d.packge);
+            }
+        }
+    }
+
+    private void initAddExports() {
+        if (addExports != null)
+            return;
+
+        addExports = new LinkedHashMap<>();
+
+        if (addExportsOpt == null)
+            return;
+
+//        System.err.println("Modules.addExports:\n   " + addExportsOpt.replace("\0", "\n   "));
+
+        Pattern ep = Pattern.compile("([^/]+)/([^=]+)=(.*)");
+        for (String s: addExportsOpt.split("\0+")) {
+            if (s.isEmpty())
+                continue;
+            Matcher em = ep.matcher(s);
+            if (!em.matches()) {
+                continue;
+            }
+
+            // Terminology comes from
+            //  -XaddExports:module/package=target,...
+            // Compare to
+            //  module module { exports package to target, ... }
+            String moduleName = em.group(1);
+            String packageName = em.group(2);
+            String targetNames = em.group(3);
+
+            ModuleSymbol msym = syms.enterModule(names.fromString(moduleName));
+            PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
+            p.modle = msym;  // TODO: do we need this?
+
+            List<ModuleSymbol> targetModules = List.nil();
+            for (String toModule : targetNames.split("[ ,]+")) {
+                ModuleSymbol m;
+                if (toModule.equals("ALL-UNNAMED")) {
+                    m = syms.unnamedModule;
+                } else {
+                    if (!SourceVersion.isName(toModule)) {
+                        // TODO: error: invalid module name
+                        continue;
+                    }
+                    m = syms.enterModule(names.fromString(toModule));
+                }
+                targetModules = targetModules.prepend(m);
+            }
+
+            Set<ExportsDirective> extra = addExports.computeIfAbsent(msym, _x -> new LinkedHashSet<>());
+            ExportsDirective d = new ExportsDirective(p, targetModules);
+            extra.add(d);
+        }
+    }
+
+    private void initAddReads() {
+        if (addReads != null)
+            return;
+
+        addReads = new LinkedHashMap<>();
+
+        if (addReadsOpt == null)
+            return;
+
+//        System.err.println("Modules.addReads:\n   " + addReadsOpt.replace("\0", "\n   "));
+
+        Pattern rp = Pattern.compile("([^=]+)=(.*)");
+        for (String s : addReadsOpt.split("\0+")) {
+            if (s.isEmpty())
+                continue;
+            Matcher rm = rp.matcher(s);
+            if (!rm.matches()) {
+                continue;
+            }
+
+            // Terminology comes from
+            //  -XaddReads:target-module=source-module,...
+            // Compare to
+            //  module target-module { requires source-module; ... }
+            String targetName = rm.group(1);
+            String sources = rm.group(2);
+
+            ModuleSymbol msym = syms.enterModule(names.fromString(targetName));
+            for (String source : sources.split("[ ,]+")) {
+                ModuleSymbol sourceModule;
+                if (source.equals("ALL-UNNAMED")) {
+                    sourceModule = syms.unnamedModule;
+                } else {
+                    if (!SourceVersion.isName(source)) {
+                        // TODO: error: invalid module name
+                        continue;
+                    }
+                    sourceModule = syms.enterModule(names.fromString(source));
+                }
+                addReads.computeIfAbsent(msym, m -> new HashSet<>())
+                        .add(new RequiresDirective(sourceModule, EnumSet.of(RequiresFlag.EXTRA)));
+            }
+        }
+    }
+
+    private void checkCyclicDependencies(JCModuleDecl mod) {
+        for (JCDirective d : mod.directives) {
+            if (!d.hasTag(Tag.REQUIRES))
+                continue;
+            JCRequires rd = (JCRequires) d;
+            Set<ModuleSymbol> nonSyntheticDeps = new HashSet<>();
+            List<ModuleSymbol> queue = List.of(rd.directive.module);
+            while (queue.nonEmpty()) {
+                ModuleSymbol current = queue.head;
+                queue = queue.tail;
+                if (!nonSyntheticDeps.add(current))
+                    continue;
+                if ((current.flags() & Flags.ACYCLIC) != 0)
+                    continue;
+                current.complete();
+                Assert.checkNonNull(current.requires, () -> current.toString());
+                for (RequiresDirective dep : current.requires) {
+                    if (!dep.flags.contains(RequiresFlag.EXTRA))
+                        queue = queue.prepend(dep.module);
+                }
+            }
+            if (nonSyntheticDeps.contains(mod.sym)) {
+                log.error(rd.moduleName.pos(), Errors.CyclicRequires(rd.directive.module));
+            }
+            mod.sym.flags_field |= Flags.ACYCLIC;
+        }
+    }
+
+    // DEBUG
+    private String toString(ModuleSymbol msym) {
+        return msym.name + "["
+                + "kind:" + msym.kind + ";"
+                + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";"
+                + "info:" + toString(msym.module_info.sourcefile) + ","
+                            + toString(msym.module_info.classfile) + ","
+                            + msym.module_info.completer
+                + "]";
+    }
+
+    // DEBUG
+    String toString(Location locn) {
+        return (locn == null) ? "--" : locn.getName();
+    }
+
+    // DEBUG
+    String toString(JavaFileObject fo) {
+        return (fo == null) ? "--" : fo.getName();
+    }
+
+    public void newRound() {
+    }
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
index 38a941b..6be12dd 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
@@ -93,10 +93,13 @@
     JCDiagnostic.Factory diags;
     public final boolean allowMethodHandles;
     public final boolean allowFunctionalInterfaceMostSpecific;
+    public final boolean allowModules;
     public final boolean checkVarargsAccessAfterResolution;
     private final boolean compactMethodDiags;
     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
 
+    private final boolean checkModuleAccess;
+
     WriteableScope polymorphicSignatureScope;
 
     protected Resolve(Context context) {
@@ -130,6 +133,12 @@
         polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
 
         inapplicableMethodException = new InapplicableMethodException(diags);
+
+        allowModules = source.allowModules();
+
+        // The following is required, for now, to support building
+        // Swing beaninfo via javadoc.
+        checkModuleAccess = !options.isSet("noModules");
     }
 
     /** error symbols, which are returned when resolution fails
@@ -309,8 +318,19 @@
                     env.toplevel.packge == c.packge();
                 break;
             default: // error recovery
+                isAccessible = true;
+                break;
             case PUBLIC:
                 isAccessible = true;
+                if (allowModules && checkModuleAccess) {
+                    ModuleSymbol currModule = env.toplevel.modle;
+                    currModule.complete();
+                    PackageSymbol p = c.packge();
+                    isAccessible =
+                        (currModule == p.modle) || currModule.visiblePackages.get(p.fullname) == p || p == syms.rootPackage;
+                } else {
+                    isAccessible = true;
+                }
                 break;
             case PROTECTED:
                 isAccessible =
@@ -1947,16 +1967,27 @@
      */
     Symbol loadClass(Env<AttrContext> env, Name name) {
         try {
-            ClassSymbol c = finder.loadClass(name);
+            ClassSymbol c = finder.loadClass(env.toplevel.modle, name);
             return isAccessible(env, c) ? c : new AccessError(c);
         } catch (ClassFinder.BadClassFile err) {
             throw err;
         } catch (CompletionFailure ex) {
+            //even if a class cannot be found in the current module and packages in modules it depends on that
+            //are exported for any or this module, the class may exist internally in some of these modules,
+            //or may exist in a module on which this module does not depend. Provide better diagnostic in
+            //such cases by looking for the class in any module:
+            for (ModuleSymbol ms : syms.getAllModules()) {
+                //do not load currently unloaded classes, to avoid too eager completion of random things in other modules:
+                ClassSymbol clazz = syms.getClass(ms, name);
+
+                if (clazz != null) {
+                    return new AccessError(clazz);
+                }
+            }
             return typeNotFound;
         }
     }
 
-
     /**
      * Find a type declared in a scope (not inherited).  Return null
      * if none is found.
@@ -2157,7 +2188,7 @@
         }
 
         if (kind.contains(KindSelector.PCK))
-            return syms.enterPackage(name);
+            return syms.lookupPackage(env.toplevel.modle, name);
         else return bestSoFar;
     }
 
@@ -2173,7 +2204,7 @@
         Symbol bestSoFar = typeNotFound;
         PackageSymbol pack = null;
         if (kind.contains(KindSelector.PCK)) {
-            pack = syms.enterPackage(fullname);
+            pack = syms.lookupPackage(env.toplevel.modle, fullname);
             if (pack.exists()) return pack;
         }
         if (kind.contains(KindSelector.TYP)) {
@@ -3920,9 +3951,15 @@
             else if ((sym.flags() & PUBLIC) != 0
                 || (env != null && this.site != null
                     && !isAccessible(env, this.site))) {
-                return diags.create(dkind, log.currentSource(),
-                        pos, "not.def.access.class.intf.cant.access",
-                    sym, sym.location());
+                if (sym.owner.kind == PCK) {
+                    return diags.create(dkind, log.currentSource(),
+                            pos, "not.def.access.package.cant.access",
+                        sym, sym.location());
+                } else {
+                    return diags.create(dkind, log.currentSource(),
+                            pos, "not.def.access.class.intf.cant.access",
+                        sym, sym.location());
+                }
             }
             else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) {
                 return diags.create(dkind, log.currentSource(),
@@ -3935,6 +3972,18 @@
                         pos, "not.def.public.cant.access", sym, sym.location());
             }
         }
+
+        private String toString(Type type) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(type);
+            if (type != null) {
+                sb.append("[tsym:").append(type.tsym);
+                if (type.tsym != null)
+                    sb.append("packge:").append(type.tsym.packge());
+                sb.append("]");
+            }
+            return sb.toString();
+        }
     }
 
     /**
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
index 04aaa83..8e8665d 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
@@ -162,6 +162,8 @@
         // if there remain any unimported toplevels (these must have
         // no classes at all), process their import statements as well.
         for (JCCompilationUnit tree : trees) {
+            if (tree.defs.nonEmpty() && tree.defs.head.hasTag(MODULEDEF))
+                continue;
             if (!tree.starImportScope.isFilled()) {
                 Env<AttrContext> topEnv = enter.topLevelEnv(tree);
                 finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); });
@@ -330,7 +332,7 @@
                                          chk.importAccessible(sym, packge);
 
                 // Import-on-demand java.lang.
-                PackageSymbol javaLang = syms.enterPackage(names.java_lang);
+                PackageSymbol javaLang = syms.enterPackage(syms.java_base, names.java_lang);
                 if (javaLang.members().isEmpty() && !javaLang.exists())
                     throw new FatalError(diags.fragment("fatal.err.no.java.lang"));
                 importAll(make.at(tree.pos()).Import(make.QualIdent(javaLang), false), javaLang, env);
@@ -358,7 +360,9 @@
                 Symbol p = env.toplevel.packge;
                 while (p.owner != syms.rootPackage) {
                     p.owner.complete(); // enter all class members of p
-                    if (syms.classes.get(p.getQualifiedName()) != null) {
+                    //need to lookup the owning module/package:
+                    PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, p.owner.getQualifiedName());
+                    if (syms.getClass(pack.modle, p.getQualifiedName()) != null) {
                         log.error(tree.pos,
                                   "pkg.clashes.with.class.of.same.name",
                                   p);
@@ -515,7 +519,7 @@
             return result;
         }
 
-        protected Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) {
+        protected Type modelMissingTypes(Env<AttrContext> env, Type t, final JCExpression tree, final boolean interfaceExpected) {
             if (!t.hasTag(ERROR))
                 return t;
 
@@ -525,19 +529,21 @@
                 @Override
                 public Type getModelType() {
                     if (modelType == null)
-                        modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree);
+                        modelType = new Synthesizer(env.toplevel.modle, getOriginalType(), interfaceExpected).visit(tree);
                     return modelType;
                 }
             };
         }
             // where:
             private class Synthesizer extends JCTree.Visitor {
+                ModuleSymbol msym;
                 Type originalType;
                 boolean interfaceExpected;
                 List<ClassSymbol> synthesizedSymbols = List.nil();
                 Type result;
 
-                Synthesizer(Type originalType, boolean interfaceExpected) {
+                Synthesizer(ModuleSymbol msym, Type originalType, boolean interfaceExpected) {
+                    this.msym = msym;
                     this.originalType = originalType;
                     this.interfaceExpected = interfaceExpected;
                 }
@@ -564,7 +570,7 @@
                     if (!tree.type.hasTag(ERROR)) {
                         result = tree.type;
                     } else {
-                        result = synthesizeClass(tree.name, syms.unnamedPackage).type;
+                        result = synthesizeClass(tree.name, msym.unnamedPackage).type;
                     }
                 }
 
@@ -654,7 +660,7 @@
                 ? Type.noType
                 : syms.objectType;
             }
-            ct.supertype_field = modelMissingTypes(supertype, extending, false);
+            ct.supertype_field = modelMissingTypes(baseEnv, supertype, extending, false);
 
             // Determine interfaces.
             ListBuffer<Type> interfaces = new ListBuffer<>();
@@ -669,7 +675,7 @@
                 } else {
                     if (all_interfaces == null)
                         all_interfaces = new ListBuffer<Type>().appendList(interfaces);
-                    all_interfaces.append(modelMissingTypes(it, iface, true));
+                    all_interfaces.append(modelMissingTypes(baseEnv, it, iface, true));
                 }
             }
 
@@ -816,8 +822,8 @@
             // but admit classes in the unnamed package which have the same
             // name as a top-level package.
             if (checkClash &&
-                sym.owner.kind == PCK && sym.owner != syms.unnamedPackage &&
-                syms.packageExists(sym.fullname)) {
+                sym.owner.kind == PCK && sym.owner != env.toplevel.modle.unnamedPackage &&
+                syms.packageExists(env.toplevel.modle, sym.fullname)) {
                 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), sym);
             }
             if (sym.owner.kind == PCK && (sym.flags_field & PUBLIC) == 0 &&
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
index caf3dc3..874f78c 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
@@ -31,6 +31,7 @@
 import java.io.OutputStreamWriter;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.nio.ByteBuffer;
@@ -42,6 +43,7 @@
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -58,6 +60,8 @@
 import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.main.OptionHelper;
 import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.util.Abort;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
@@ -192,12 +196,34 @@
                         Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
                 Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
                 Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
-                return constr.newInstance(urls, thisClassLoader);
+                return ensureReadable(constr.newInstance(urls, thisClassLoader));
             } catch (ReflectiveOperationException t) {
                 // ignore errors loading user-provided class loader, fall through
             }
         }
-        return new URLClassLoader(urls, thisClassLoader);
+        return ensureReadable(new URLClassLoader(urls, thisClassLoader));
+    }
+
+    /**
+     * Ensures that the unnamed module of the given classloader is readable to this
+     * module.
+     */
+    private ClassLoader ensureReadable(ClassLoader targetLoader) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Method getUnnamedModuleMethod = ClassLoader.class.getMethod("getUnnamedModule");
+            Object targetModule = getUnnamedModuleMethod.invoke(targetLoader);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new Abort(e);
+        }
+        return targetLoader;
     }
 
     public boolean isDefaultBootClassPath() {
@@ -284,8 +310,14 @@
      */
     public boolean handleOptions(Map<Option, String> map) {
         boolean ok = true;
-        for (Map.Entry<Option, String> e: map.entrySet())
-            ok = ok & handleOption(e.getKey(), e.getValue());
+        for (Map.Entry<Option, String> e: map.entrySet()) {
+            try {
+                ok = ok & handleOption(e.getKey(), e.getValue());
+            } catch (IllegalArgumentException ex) {
+                log.error(Errors.IllegalArgumentForOption(e.getKey().getText(), ex.getMessage()));
+                ok = false;
+            }
+        }
         return ok;
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
index 6ca7bcd..20f7a48 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
@@ -201,6 +201,8 @@
             if (Files.exists(dir)) {
                 try (DirectoryStream<Path> modules = Files.newDirectoryStream(dir)) {
                     for (Path module: modules) {
+                        if (Files.isSymbolicLink(module))
+                            module = Files.readSymbolicLink(module);
                         Path p = rd.resolveAgainst(module);
                         if (!Files.exists(p))
                             continue;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
index 1fc2fa1..496c039 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
@@ -47,12 +47,14 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -70,6 +72,10 @@
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.ModuleWrappers.Configuration;
+import com.sun.tools.javac.util.ModuleWrappers.Layer;
+import com.sun.tools.javac.util.ModuleWrappers.ModuleFinder;
+import com.sun.tools.javac.util.ModuleWrappers.ServiceLoaderHelper;
 
 import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
 
@@ -421,16 +427,7 @@
                                boolean recurse,
                                ListBuffer<JavaFileObject> resultList)
             throws IOException {
-        // Very temporary and obnoxious interim hack
-        if (container.endsWith("bootmodules.jimage")) {
-            System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
-            container = Locations.JRT_MARKER_FILE;
-        } else if (container.getNameCount() > 0 && container.getFileName().toString().endsWith(".jimage")) {
-            System.err.println("Warning: reference to " + container + " ignored");
-            return;
-        }
-
-        if (container == Locations.JRT_MARKER_FILE) {
+        if (Files.isRegularFile(container) && container.equals(Locations.thisSystemModules)) {
             try {
                 listJRTImage(subdirectory,
                         fileKinds,
@@ -443,7 +440,7 @@
             return;
         }
 
-        if  (fsInfo.isDirectory(container)) {
+        if  (Files.isDirectory(container)) {
             listDirectory(container, null,
                           subdirectory,
                           fileKinds,
@@ -452,7 +449,7 @@
             return;
         }
 
-        if (Files.exists(container)) {
+        if (Files.isRegularFile(container)) {
             listArchive(container,
                     subdirectory,
                     fileKinds,
@@ -530,6 +527,7 @@
             return;
         }
 
+        locations.close();
         for (FileSystem fs: fileSystems.values()) {
             fs.close();
         }
@@ -604,7 +602,8 @@
 
     @Override @DefinedBy(Api.COMPILER)
     public boolean hasLocation(Location location) {
-        return getLocation(location) != null;
+        nullCheck(location);
+        return locations.hasLocation(location);
     }
 
     @Override @DefinedBy(Api.COMPILER)
@@ -645,14 +644,14 @@
             return null;
 
         for (Path file: path) {
-            if (file == Locations.JRT_MARKER_FILE) {
+            if (file.equals(Locations.thisSystemModules)) {
                 JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
                 if (symbolFileEnabled && e.ctSym.hidden)
                     continue;
                 Path p = e.files.get(name.basename());
                 if (p != null)
                     return PathFileObject.forJRTPath(this, p);
-            } else if (fsInfo.isDirectory(file)) {
+            } else if (Files.isDirectory(file)) {
                 try {
                     Path f = name.resolveAgainst(file);
                     if (Files.exists(f))
@@ -660,7 +659,7 @@
                                 fsInfo.getCanonicalFile(f), f);
                 } catch (InvalidPathException ignore) {
                 }
-            } else if (Files.exists(file)) {
+            } else if (Files.isRegularFile(file)) {
                 FileSystem fs = getFileSystem(file);
                 if (fs != null) {
                     Path fsRoot = fs.getRootDirectories().iterator().next();
@@ -830,6 +829,69 @@
     }
 
     @Override @DefinedBy(Api.COMPILER)
+    public Location getModuleLocation(Location location, String moduleName) throws IOException {
+        nullCheck(location);
+        nullCheck(moduleName);
+        return locations.getModuleLocation(location, moduleName);
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws IOException {
+        nullCheck(location);
+        nullCheck(service);
+        if (location.isModuleLocation()) {
+            Collection<Path> paths = locations.getLocation(location);
+            ModuleFinder finder = ModuleFinder.of(paths.toArray(new Path[paths.size()]));
+            Layer bootLayer = Layer.boot();
+            Configuration cf = bootLayer.configuration().resolveRequiresAndUses(ModuleFinder.empty(), finder, Collections.emptySet());
+            Layer layer = bootLayer.defineModulesWithOneLoader(cf, ClassLoader.getSystemClassLoader());
+            return ServiceLoaderHelper.load(layer, service);
+        } else {
+            return ServiceLoader.load(service, getClassLoader(location));
+        }
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        nullCheck(location);
+        if (!(fo instanceof PathFileObject))
+            throw new IllegalArgumentException(fo.getName());
+        int depth = 1; // allow 1 for filename
+        if (pkgName != null && !pkgName.isEmpty()) {
+            depth += 1;
+            for (int i = 0; i < pkgName.length(); i++) {
+                switch (pkgName.charAt(i)) {
+                    case '/': case '.':
+                        depth++;
+                }
+            }
+        }
+        Path p = Locations.normalize(((PathFileObject) fo).path);
+        int fc = p.getNameCount();
+        if (depth < fc) {
+            Path root = p.getRoot();
+            Path subpath = p.subpath(0, fc - depth);
+            Path dir = (root == null) ? subpath : root.resolve(subpath);
+            // need to find dir in location
+            return locations.getModuleLocation(location, dir);
+        } else {
+            return null;
+        }
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public String inferModuleName(Location location) {
+        nullCheck(location);
+        return locations.inferModuleName(location);
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        nullCheck(location);
+        return locations.listModuleLocations(location);
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
     public Path asPath(FileObject file) {
         if (file instanceof PathFileObject) {
             return ((PathFileObject) file).path;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
index aec0e7f..f3a7b61 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
@@ -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
@@ -25,15 +25,23 @@
 
 package com.sun.tools.javac.file;
 
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -43,15 +51,20 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 
+import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
@@ -59,13 +72,14 @@
 
 import com.sun.tools.javac.code.Lint;
 import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Pair;
 import com.sun.tools.javac.util.StringUtils;
 
-import static javax.tools.StandardLocation.CLASS_PATH;
 import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
-import static javax.tools.StandardLocation.SOURCE_PATH;
 
 import static com.sun.tools.javac.main.Option.BOOTCLASSPATH;
 import static com.sun.tools.javac.main.Option.DJAVA_ENDORSED_DIRS;
@@ -103,16 +117,35 @@
      */
     private boolean warn;
 
-    // Used by Locations(for now) to indicate that the PLATFORM_CLASS_PATH
-    // should use the jrt: file system.
-    // When Locations has been converted to use java.nio.file.Path,
-    // Locations can use Paths.get(URI.create("jrt:"))
-    static final Path JRT_MARKER_FILE = Paths.get("JRT_MARKER_FILE");
+    private ModuleNameReader moduleNameReader;
+
+    static final Path javaHome = Paths.get(System.getProperty("java.home"));
+    static final Path thisSystemModules = javaHome.resolve("lib").resolve("modules");
+
+    Map<Path, FileSystem> fileSystems = new LinkedHashMap<>();
+    List<Closeable> closeables = new ArrayList<>();
 
     Locations() {
         initHandlers();
     }
 
+    public void close() throws IOException {
+        ListBuffer<IOException> list = new ListBuffer<>();
+        closeables.forEach(closeable -> {
+            try {
+                closeable.close();
+            } catch (IOException ex) {
+                list.add(ex);
+            }
+        });
+        if (list.nonEmpty()) {
+            IOException ex = new IOException();
+            for (IOException e: list)
+                ex.addSuppressed(e);
+            throw ex;
+        }
+    }
+
     // could replace Lint by "boolean warn"
     void update(Log log, Lint lint, FSInfo fsInfo) {
         this.log = log;
@@ -269,10 +302,13 @@
 
             if (fsInfo.isFile(file)) {
                 /* File is an ordinary file. */
-                if (!isArchive(file) && !file.getFileName().toString().endsWith(".jimage")) {
+                if (!isArchive(file)
+                        && !file.getFileName().toString().endsWith(".jmod")
+                        && !file.endsWith("modules")) {
                     /* Not a recognized extension; open it to see if
                      it looks like a valid zip file. */
                     try {
+                        // TODO: use of ZipFile should be updated
                         ZipFile z = new ZipFile(file.toFile());
                         z.close();
                         if (warn) {
@@ -295,7 +331,7 @@
             super.add(file);
             canonicalValues.add(canonFile);
 
-            if (expandJarClassPaths && fsInfo.isFile(file) && !file.getFileName().toString().endsWith(".jimage")) {
+            if (expandJarClassPaths && fsInfo.isFile(file) && !file.endsWith("modules")) {
                 addJarClassPath(file, warn);
             }
         }
@@ -316,15 +352,74 @@
     }
 
     /**
-     * Base class for handling support for the representation of Locations. Implementations are
-     * responsible for handling the interactions between the command line options for a location,
-     * and API access via setLocation.
+     * Base class for handling support for the representation of Locations.
+     *
+     * Locations are (by design) opaque handles that can easily be implemented
+     * by enums like StandardLocation. Within JavacFileManager, each Location
+     * has an associated LocationHandler, which provides much of the appropriate
+     * functionality for the corresponding Location.
      *
      * @see #initHandlers
      * @see #getHandler
      */
     protected abstract class LocationHandler {
 
+        /**
+         * @see JavaFileManager#handleOption
+         */
+        abstract boolean handleOption(Option option, String value);
+
+        /**
+         * @see StandardJavaFileManager#hasLocation
+         */
+        boolean isSet() {
+            return (getPaths() != null);
+        }
+
+        /**
+         * @see StandardJavaFileManager#getLocation
+         */
+        abstract Collection<Path> getPaths();
+
+        /**
+         * @see StandardJavaFileManager#setLocation
+         */
+        abstract void setPaths(Iterable<? extends Path> files) throws IOException;
+
+        /**
+         * @see JavaFileManager#getModuleLocation(Location, String)
+         */
+        Location getModuleLocation(String moduleName) throws IOException {
+            return null;
+        }
+
+        /**
+         * @see JavaFileManager#getModuleLocation(Location, JavaFileObject, String)
+         */
+        Location getModuleLocation(Path dir) {
+            return null;
+        }
+
+        /**
+         * @see JavaFileManager#inferModuleName
+         */
+        String inferModuleName() {
+            return null;
+        }
+
+        /**
+         * @see JavaFileManager#listModuleLocations
+         */
+        Iterable<Set<Location>> listModuleLocations() throws IOException {
+            return null;
+        }
+    }
+
+    /**
+     * A LocationHandler for a given Location, and associated set of options.
+     */
+    private abstract class BasicLocationHandler extends LocationHandler {
+
         final Location location;
         final Set<Option> options;
 
@@ -336,37 +431,23 @@
          * @param options the options affecting this location
          * @see #initHandlers
          */
-        protected LocationHandler(Location location, Option... options) {
+        protected BasicLocationHandler(Location location, Option... options) {
             this.location = location;
             this.options = options.length == 0
                     ? EnumSet.noneOf(Option.class)
                     : EnumSet.copyOf(Arrays.asList(options));
         }
-
-        /**
-         * @see JavaFileManager#handleOption
-         */
-        abstract boolean handleOption(Option option, String value);
-
-        /**
-         * @see StandardJavaFileManager#getLocation
-         */
-        abstract Collection<Path> getLocation();
-
-        /**
-         * @see StandardJavaFileManager#setLocation
-         */
-        abstract void setLocation(Iterable<? extends Path> files) throws IOException;
     }
 
     /**
      * General purpose implementation for output locations, such as -d/CLASS_OUTPUT and
-     * -s/SOURCE_OUTPUT. All options are treated as equivalent (i.e. aliases.) The value is a single
-     * file, possibly null.
+     * -s/SOURCE_OUTPUT. All options are treated as equivalent (i.e. aliases.)
+     * The value is a single file, possibly null.
      */
-    private class OutputLocationHandler extends LocationHandler {
+    private class OutputLocationHandler extends BasicLocationHandler {
 
         private Path outputDir;
+        private Map<String, Location> moduleLocations;
 
         OutputLocationHandler(Location location, Option... options) {
             super(location, options);
@@ -387,12 +468,12 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             return (outputDir == null) ? null : Collections.singleton(outputDir);
         }
 
         @Override
-        void setLocation(Iterable<? extends Path> files) throws IOException {
+        void setPaths(Iterable<? extends Path> files) throws IOException {
             if (files == null) {
                 outputDir = null;
             } else {
@@ -411,15 +492,32 @@
                 }
                 outputDir = dir;
             }
+            moduleLocations = null;
+        }
+
+        @Override
+        Location getModuleLocation(String name) {
+            if (moduleLocations == null)
+                moduleLocations = new HashMap<>();
+            Location l = moduleLocations.get(name);
+            if (l == null) {
+                l = new ModuleLocationHandler(location.getName() + "[" + name + "]",
+                        name,
+                        Collections.singleton(outputDir.resolve(name)),
+                        true, false);
+                moduleLocations.put(name, l);
+            }
+            return l;
         }
     }
 
     /**
-     * General purpose implementation for search path locations, such as -sourcepath/SOURCE_PATH and
-     * -processorPath/ANNOTATION_PROCESSOR_PATH. All options are treated as equivalent (i.e. aliases.)
+     * General purpose implementation for search path locations,
+     * such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESSOR_PATH.
+     * All options are treated as equivalent (i.e. aliases.)
      * The value is an ordered set of files and/or directories.
      */
-    private class SimpleLocationHandler extends LocationHandler {
+    private class SimpleLocationHandler extends BasicLocationHandler {
 
         protected Collection<Path> searchPath;
 
@@ -438,12 +536,12 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             return searchPath;
         }
 
         @Override
-        void setLocation(Iterable<? extends Path> files) {
+        void setPaths(Iterable<? extends Path> files) {
             SearchPath p;
             if (files == null) {
                 p = computePath(null);
@@ -463,8 +561,8 @@
     }
 
     /**
-     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH. If no value is given, a default
-     * is provided, based on system properties and other values.
+     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
+     * If no value is given, a default is provided, based on system properties and other values.
      */
     private class ClassPathLocationHandler extends SimpleLocationHandler {
 
@@ -474,7 +572,7 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             lazy();
             return searchPath;
         }
@@ -511,19 +609,22 @@
 
         private void lazy() {
             if (searchPath == null) {
-                setLocation(null);
+                setPaths(null);
             }
         }
     }
 
     /**
-     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH. Various options are supported for
-     * different components of the platform class path. Setting a value with setLocation overrides
-     * all existing option values. Setting any option overrides any value set with setLocation, and
-     * reverts to using default values for options that have not been set. Setting -bootclasspath or
-     * -Xbootclasspath overrides any existing value for -Xbootclasspath/p: and -Xbootclasspath/a:.
+     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH.
+     * Various options are supported for different components of the
+     * platform class path.
+     * Setting a value with setLocation overrides all existing option values.
+     * Setting any option overrides any value set with setLocation, and
+     * reverts to using default values for options that have not been set.
+     * Setting -bootclasspath or -Xbootclasspath overrides any existing
+     * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
      */
-    private class BootClassPathLocationHandler extends LocationHandler {
+    private class BootClassPathLocationHandler extends BasicLocationHandler {
 
         private Collection<Path> searchPath;
         final Map<Option, String> optionValues = new EnumMap<>(Option.class);
@@ -579,13 +680,13 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             lazy();
             return searchPath;
         }
 
         @Override
-        void setLocation(Iterable<? extends Path> files) {
+        void setPaths(Iterable<? extends Path> files) {
             if (files == null) {
                 searchPath = null;  // reset to "uninitialized"
             } else {
@@ -597,8 +698,6 @@
         }
 
         SearchPath computePath() throws IOException {
-            String java_home = System.getProperty("java.home");
-
             SearchPath path = new SearchPath();
 
             String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
@@ -618,7 +717,7 @@
                 path.addFiles(bootclasspathOpt);
             } else {
                 // Standard system classes for this compiler's release.
-                Collection<Path> systemClasses = systemClasses(java_home);
+                Collection<Path> systemClasses = systemClasses();
                 if (systemClasses != null) {
                     path.addFiles(systemClasses, false);
                 } else {
@@ -637,7 +736,7 @@
                 path.addDirectories(extdirsOpt);
             } else {
                 // Add lib/jfxrt.jar to the search path
-               Path jfxrt = Paths.get(java_home, "lib", "jfxrt.jar");
+               Path jfxrt = javaHome.resolve("lib/jfxrt.jar");
                 if (Files.exists(jfxrt)) {
                     path.addFile(jfxrt, false);
                 }
@@ -658,21 +757,14 @@
          *
          * @throws UncheckedIOException if an I/O errors occurs
          */
-        private Collection<Path> systemClasses(String java_home) throws IOException {
-            // Return .jimage files if available
-            Path libModules = Paths.get(java_home, "lib", "modules");
-            if (Files.exists(libModules)) {
-                try (Stream<Path> files = Files.list(libModules)) {
-                    boolean haveJImageFiles =
-                            files.anyMatch(f -> f.getFileName().toString().endsWith(".jimage"));
-                    if (haveJImageFiles) {
-                        return addAdditionalBootEntries(Collections.singleton(JRT_MARKER_FILE));
-                    }
-                }
+        private Collection<Path> systemClasses() throws IOException {
+            // Return "modules" jimage file if available
+            if (Files.isRegularFile(thisSystemModules)) {
+                return addAdditionalBootEntries(Collections.singleton(thisSystemModules));
             }
 
             // Exploded module image
-            Path modules = Paths.get(java_home, "modules");
+            Path modules = javaHome.resolve("modules");
             if (Files.isDirectory(modules.resolve("java.base"))) {
                 try (Stream<Path> listedModules = Files.list(modules)) {
                     return addAdditionalBootEntries(listedModules.collect(Collectors.toList()));
@@ -686,18 +778,18 @@
         //ensure bootclasspath prepends/appends are reflected in the systemClasses
         private Collection<Path> addAdditionalBootEntries(Collection<Path> modules) throws IOException {
             String files = System.getProperty("sun.boot.class.path");
-
             if (files == null)
                 return modules;
 
             Set<Path> paths = new LinkedHashSet<>();
 
+            // The JVM no longer supports -Xbootclasspath/p:, so any interesting
+            // entries should be appended to the set of modules.
+
+            paths.addAll(modules);
+
             for (String s : files.split(Pattern.quote(File.pathSeparator))) {
-                if (s.endsWith(".jimage")) {
-                    paths.addAll(modules);
-                } else if (!s.isEmpty()) {
-                    paths.add(Paths.get(s));
-                }
+                paths.add(Paths.get(s));
             }
 
             return paths;
@@ -715,6 +807,690 @@
         }
     }
 
+    /**
+     * A LocationHander to represent modules found from a module-oriented
+     * location such as MODULE_SOURCE_PATH, UPGRADE_MODULE_PATH,
+     * SYSTEM_MODULES and MODULE_PATH.
+     *
+     * The Location can be specified to accept overriding classes from the
+     * -Xpatch:dir parameter.
+     */
+    private class ModuleLocationHandler extends LocationHandler implements Location {
+        protected final String name;
+        protected final String moduleName;
+        protected final Collection<Path> searchPath;
+        protected final Collection<Path> searchPathWithOverrides;
+        protected final boolean output;
+
+        ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath,
+                boolean output, boolean allowOverrides) {
+            this.name = name;
+            this.moduleName = moduleName;
+            this.searchPath = searchPath;
+            this.output = output;
+
+            if (allowOverrides) {
+                if (patchMap != null) {
+                    SearchPath mPatch = patchMap.get(moduleName);
+                    if (mPatch != null) {
+                        SearchPath sp = new SearchPath();
+                        sp.addAll(mPatch);
+                        sp.addAll(searchPath);
+                        searchPathWithOverrides = sp;
+                    } else {
+                        searchPathWithOverrides = searchPath;
+                    }
+                } else {
+                     // for old style patch option; retained for transition
+                    Set<Path> overrides = new LinkedHashSet<>();
+                    if (moduleOverrideSearchPath != null) {
+                       for (Path p: moduleOverrideSearchPath) {
+                           Path o = p.resolve(moduleName);
+                           if (Files.isDirectory(o)) {
+                               overrides.add(o);
+                           }
+                       }
+                    }
+
+                    if (!overrides.isEmpty()) {
+                        overrides.addAll(searchPath);
+                        searchPathWithOverrides = overrides;
+                    } else {
+                        searchPathWithOverrides = searchPath;
+                    }
+                }
+            } else {
+                searchPathWithOverrides = searchPath;
+            }
+        }
+
+        @Override // defined by Location
+        public String getName() {
+            return name;
+        }
+
+        @Override // defined by Location
+        public boolean isOutputLocation() {
+            return output;
+        }
+
+        @Override // defined by LocationHandler
+        boolean handleOption(Option option, String value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override // defined by LocationHandler
+        Collection<Path> getPaths() {
+            // For now, we always return searchPathWithOverrides. This may differ from the
+            // JVM behavior if there is a module-info.class to be found in the overriding
+            // classes.
+            return searchPathWithOverrides;
+        }
+
+        @Override // defined by LocationHandler
+        void setPaths(Iterable<? extends Path> files) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override // defined by LocationHandler
+        String inferModuleName() {
+            return moduleName;
+        }
+    }
+
+    /**
+     * A LocationHandler for simple module-oriented search paths,
+     * like UPGRADE_MODULE_PATH and MODULE_PATH.
+     */
+    private class ModulePathLocationHandler extends SimpleLocationHandler {
+        ModulePathLocationHandler(Location location, Option... options) {
+            super(location, options);
+        }
+
+        @Override
+        public boolean handleOption(Option option, String value) {
+            if (!options.contains(option)) {
+                return false;
+            }
+            setPaths(value == null ? null : getPathEntries(value));
+            return true;
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() {
+            if (searchPath == null)
+                return Collections.emptyList();
+
+            return () -> new ModulePathIterator();
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> paths) {
+            if (paths != null) {
+                for (Path p: paths) {
+                    checkValidModulePathEntry(p);
+                }
+            }
+            super.setPaths(paths);
+        }
+
+        private void checkValidModulePathEntry(Path p) {
+            if (Files.isDirectory(p)) {
+                // either an exploded module or a directory of modules
+                return;
+            }
+
+            String name = p.getFileName().toString();
+            int lastDot = name.lastIndexOf(".");
+            if (lastDot > 0) {
+                switch (name.substring(lastDot)) {
+                    case ".jar":
+                    case ".jmod":
+                        return;
+                }
+            }
+            throw new IllegalArgumentException(p.toString());
+        }
+
+        class ModulePathIterator implements Iterator<Set<Location>> {
+            Iterator<Path> pathIter = searchPath.iterator();
+            int pathIndex = 0;
+            Set<Location> next = null;
+
+            @Override
+            public boolean hasNext() {
+                if (next != null)
+                    return true;
+
+                while (next == null) {
+                    if (pathIter.hasNext()) {
+                        Path path = pathIter.next();
+                        if (Files.isDirectory(path)) {
+                            next = scanDirectory(path);
+                        } else {
+                            next = scanFile(path);
+                        }
+                        pathIndex++;
+                    } else
+                        return false;
+                }
+                return true;
+            }
+
+            @Override
+            public Set<Location> next() {
+                hasNext();
+                if (next != null) {
+                    Set<Location> result = next;
+                    next = null;
+                    return result;
+                }
+                throw new NoSuchElementException();
+            }
+
+            private Set<Location> scanDirectory(Path path) {
+                Set<Path> paths = new LinkedHashSet<>();
+                Path moduleInfoClass = null;
+                try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
+                    for (Path entry: stream) {
+                        if (entry.endsWith("module-info.class")) {
+                            moduleInfoClass = entry;
+                            break;  // no need to continue scanning
+                        }
+                        paths.add(entry);
+                    }
+                } catch (DirectoryIteratorException | IOException ignore) {
+                    log.error(Errors.LocnCantReadDirectory(path));
+                    return Collections.emptySet();
+                }
+
+                if (moduleInfoClass != null) {
+                    // It's an exploded module directly on the module path.
+                    // We can't infer module name from the directory name, so have to
+                    // read module-info.class.
+                    try {
+                        String moduleName = readModuleName(moduleInfoClass);
+                        String name = location.getName()
+                                + "[" + pathIndex + ":" + moduleName + "]";
+                        ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
+                                Collections.singleton(path), false, true);
+                        return Collections.singleton(l);
+                    } catch (ModuleNameReader.BadClassFile e) {
+                        log.error(Errors.LocnBadModuleInfo(path));
+                        return Collections.emptySet();
+                    } catch (IOException e) {
+                        log.error(Errors.LocnCantReadFile(path));
+                        return Collections.emptySet();
+                    }
+                }
+
+                // A directory of modules
+                Set<Location> result = new LinkedHashSet<>();
+                int index = 0;
+                for (Path entry : paths) {
+                    Pair<String,Path> module = inferModuleName(entry);
+                    if (module == null) {
+                        // diagnostic reported if necessary; skip to next
+                        continue;
+                    }
+                    String moduleName = module.fst;
+                    Path modulePath = module.snd;
+                    String name = location.getName()
+                            + "[" + pathIndex + "." + (index++) + ":" + moduleName + "]";
+                    ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
+                            Collections.singleton(modulePath), false, true);
+                    result.add(l);
+                }
+                return result;
+            }
+
+            private Set<Location> scanFile(Path path) {
+                Pair<String,Path> module = inferModuleName(path);
+                if (module == null) {
+                    // diagnostic reported if necessary
+                    return Collections.emptySet();
+                }
+                String moduleName = module.fst;
+                Path modulePath = module.snd;
+                String name = location.getName()
+                        + "[" + pathIndex + ":" + moduleName + "]";
+                ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
+                        Collections.singleton(modulePath), false, true);
+                return Collections.singleton(l);
+            }
+
+            private Pair<String,Path> inferModuleName(Path p) {
+                if (Files.isDirectory(p)) {
+                    if (Files.exists(p.resolve("module-info.class"))) {
+                        String name = p.getFileName().toString();
+                        if (SourceVersion.isName(name))
+                            return new Pair<>(name, p);
+                    }
+                    return null;
+                }
+
+                if (p.getFileName().toString().endsWith(".jar")) {
+                    try (FileSystem fs = FileSystems.newFileSystem(p, null)) {
+                        Path moduleInfoClass = fs.getPath("module-info.class");
+                        if (Files.exists(moduleInfoClass)) {
+                            String moduleName = readModuleName(moduleInfoClass);
+                            return new Pair<>(moduleName, p);
+                        }
+                    } catch (ModuleNameReader.BadClassFile e) {
+                        log.error(Errors.LocnBadModuleInfo(p));
+                        return null;
+                    } catch (IOException e) {
+                        log.error(Errors.LocnCantReadFile(p));
+                        return null;
+                    }
+
+                    //automatic module:
+                    String fn = p.getFileName().toString();
+                    //from ModulePath.deriveModuleDescriptor:
+
+                    // drop .jar
+                    String mn = fn.substring(0, fn.length()-4);
+
+                    // find first occurrence of -${NUMBER}. or -${NUMBER}$
+                    Matcher matcher = Pattern.compile("-(\\d+(\\.|$))").matcher(mn);
+                    if (matcher.find()) {
+                        int start = matcher.start();
+
+                        mn = mn.substring(0, start);
+                    }
+
+                    // finally clean up the module name
+                    mn =  mn.replaceAll("[^A-Za-z0-9]", ".")  // replace non-alphanumeric
+                            .replaceAll("(\\.)(\\1)+", ".")   // collapse repeating dots
+                            .replaceAll("^\\.", "")           // drop leading dots
+                            .replaceAll("\\.$", "");          // drop trailing dots
+
+
+                    if (!mn.isEmpty()) {
+                        return new Pair<>(mn, p);
+                    }
+
+                    log.error(Errors.LocnCantGetModuleNameForJar(p));
+                    return null;
+                }
+
+                if (p.getFileName().toString().endsWith(".jmod")) {
+                    try {
+                        FileSystem fs = fileSystems.get(p);
+                        if (fs == null) {
+                            URI uri = URI.create("jar:" + p.toUri());
+                            fs = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
+                            try {
+                                Path moduleInfoClass = fs.getPath("classes/module-info.class");
+                                String moduleName = readModuleName(moduleInfoClass);
+                                Path modulePath = fs.getPath("classes");
+                                fileSystems.put(p, fs);
+                                closeables.add(fs);
+                                fs = null; // prevent fs being closed in the finally clause
+                                return new Pair<>(moduleName, modulePath);
+                            } finally {
+                                if (fs != null)
+                                    fs.close();
+                            }
+                        }
+                    } catch (ProviderNotFoundException e) {
+                        // will be thrown if the file is not a valid zip file
+                        log.error(Errors.LocnCantReadFile(p));
+                        return null;
+                    } catch (ModuleNameReader.BadClassFile e) {
+                        log.error(Errors.LocnBadModuleInfo(p));
+                    } catch (IOException e) {
+                        log.error(Errors.LocnCantReadFile(p));
+                        return null;
+                    }
+                }
+
+                if (warn && false) {  // temp disable
+                    log.warning(Warnings.LocnUnknownFileOnModulePath(p));
+                }
+                return null;
+            }
+
+            private String readModuleName(Path path) throws IOException, ModuleNameReader.BadClassFile {
+                if (moduleNameReader == null)
+                    moduleNameReader = new ModuleNameReader();
+                return moduleNameReader.readModuleName(path);
+            }
+        }
+
+    }
+
+    private class ModuleSourcePathLocationHandler extends BasicLocationHandler {
+
+        private Map<String, Location> moduleLocations;
+        private Map<Path, Location> pathLocations;
+
+
+        ModuleSourcePathLocationHandler() {
+            super(StandardLocation.MODULE_SOURCE_PATH,
+                    Option.MODULESOURCEPATH);
+        }
+
+        @Override
+        boolean handleOption(Option option, String value) {
+            init(value);
+            return true;
+        }
+
+        void init(String value) {
+            Collection<String> segments = new ArrayList<>();
+            for (String s: value.split(File.pathSeparator)) {
+                expandBraces(s, segments);
+            }
+
+            Map<String, Collection<Path>> map = new LinkedHashMap<>();
+            final String MARKER = "*";
+            for (String seg: segments) {
+                int markStart = seg.indexOf(MARKER);
+                if (markStart == -1) {
+                    add(map, Paths.get(seg), null);
+                } else {
+                    if (markStart == 0 || !isSeparator(seg.charAt(markStart - 1))) {
+                        throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
+                    }
+                    Path prefix = Paths.get(seg.substring(0, markStart - 1));
+                    Path suffix;
+                    int markEnd = markStart + MARKER.length();
+                    if (markEnd == seg.length()) {
+                        suffix = null;
+                    } else if (!isSeparator(seg.charAt(markEnd))
+                            || seg.indexOf(MARKER, markEnd) != -1) {
+                        throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
+                    } else {
+                        suffix = Paths.get(seg.substring(markEnd + 1));
+                    }
+                    add(map, prefix, suffix);
+                }
+            }
+
+            moduleLocations = new LinkedHashMap<>();
+            pathLocations = new LinkedHashMap<>();
+            map.forEach((k, v) -> {
+                String name = location.getName() + "[" + k + "]";
+                ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false, false);
+                moduleLocations.put(k, h);
+                v.forEach(p -> pathLocations.put(normalize(p), h));
+            });
+        }
+
+        private boolean isSeparator(char ch) {
+            // allow both separators on Windows
+            return (ch == File.separatorChar) || (ch == '/');
+        }
+
+        void add(Map<String, Collection<Path>> map, Path prefix, Path suffix) {
+            if (!Files.isDirectory(prefix)) {
+                if (warn) {
+                    String key = Files.exists(prefix)
+                            ? "dir.path.element.not.directory"
+                            : "dir.path.element.not.found";
+                    log.warning(Lint.LintCategory.PATH, key, prefix);
+                }
+                return;
+            }
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(prefix, path -> Files.isDirectory(path))) {
+                for (Path entry: stream) {
+                    Path path = (suffix == null) ? entry : entry.resolve(suffix);
+                    if (Files.isDirectory(path)) {
+                        String name = entry.getFileName().toString();
+                        Collection<Path> paths = map.get(name);
+                        if (paths == null)
+                            map.put(name, paths = new ArrayList<>());
+                        paths.add(path);
+                    }
+                }
+            } catch (IOException e) {
+                // TODO? What to do?
+                System.err.println(e);
+            }
+        }
+
+        private void expandBraces(String value, Collection<String> results) {
+            int depth = 0;
+            int start = -1;
+            String prefix = null;
+            String suffix = null;
+            for (int i = 0; i < value.length(); i++) {
+                switch (value.charAt(i)) {
+                    case '{':
+                        depth++;
+                        if (depth == 1) {
+                            prefix = value.substring(0, i);
+                            suffix = value.substring(getMatchingBrace(value, i) + 1);
+                            start = i + 1;
+                        }
+                        break;
+
+                    case ',':
+                        if (depth == 1) {
+                            String elem = value.substring(start, i);
+                            expandBraces(prefix + elem + suffix, results);
+                            start = i + 1;
+                        }
+                        break;
+
+                    case '}':
+                        switch (depth) {
+                            case 0:
+                                throw new IllegalArgumentException("mismatched braces");
+
+                            case 1:
+                                String elem = value.substring(start, i);
+                                expandBraces(prefix + elem + suffix, results);
+                                return;
+
+                            default:
+                                depth--;
+                        }
+                        break;
+                }
+            }
+            if (depth > 0)
+                throw new IllegalArgumentException("mismatched braces");
+            results.add(value);
+        }
+
+        int getMatchingBrace(String value, int offset) {
+            int depth = 1;
+            for (int i = offset + 1; i < value.length(); i++) {
+                switch (value.charAt(i)) {
+                    case '{':
+                        depth++;
+                        break;
+
+                    case '}':
+                        if (--depth == 0)
+                            return i;
+                        break;
+                }
+            }
+            throw new IllegalArgumentException("mismatched braces");
+        }
+
+        @Override
+        boolean isSet() {
+            return (moduleLocations != null);
+        }
+
+        @Override
+        Collection<Path> getPaths() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> files) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        Location getModuleLocation(String name) {
+            return (moduleLocations == null) ? null : moduleLocations.get(name);
+        }
+
+        @Override
+        Location getModuleLocation(Path dir) {
+            return (pathLocations == null) ? null : pathLocations.get(dir);
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() {
+            if (moduleLocations == null)
+                return Collections.emptySet();
+            Set<Location> locns = new LinkedHashSet<>();
+            moduleLocations.forEach((k, v) -> locns.add(v));
+            return Collections.singleton(locns);
+        }
+
+    }
+
+    private class SystemModulesLocationHandler extends BasicLocationHandler {
+        private Path javaHome;
+        private Path modules;
+        private Map<String, ModuleLocationHandler> systemModules;
+
+        SystemModulesLocationHandler() {
+            super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM);
+            javaHome = Paths.get(System.getProperty("java.home"));
+        }
+
+        @Override
+        boolean handleOption(Option option, String value) {
+            if (!options.contains(option)) {
+                return false;
+            }
+
+            if (value == null) {
+                javaHome = Paths.get(System.getProperty("java.home"));
+            } else if (value.equals("none")) {
+                javaHome = null;
+            } else {
+                update(Paths.get(value));
+            }
+
+            modules = null;
+            return true;
+        }
+
+        @Override
+        Collection<Path> getPaths() {
+            return (javaHome == null) ? null : Collections.singleton(javaHome);
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> files) throws IOException {
+            if (files == null) {
+                javaHome = null;
+            } else {
+                Iterator<? extends Path> pathIter = files.iterator();
+                if (!pathIter.hasNext()) {
+                    throw new IllegalArgumentException("empty path for directory"); // TODO: FIXME
+                }
+                Path dir = pathIter.next();
+                if (pathIter.hasNext()) {
+                    throw new IllegalArgumentException("path too long for directory"); // TODO: FIXME
+                }
+                if (!Files.exists(dir)) {
+                    throw new FileNotFoundException(dir + ": does not exist");
+                } else if (!Files.isDirectory(dir)) {
+                    throw new IOException(dir + ": not a directory");
+                }
+                update(dir);
+            }
+        }
+
+        private void update(Path p) {
+            if (!isCurrentPlatform(p) && !Files.exists(p.resolve("jrt-fs.jar")) && !Files.exists(javaHome.resolve("modules")))
+                throw new IllegalArgumentException(p.toString());
+            javaHome = p;
+            modules = null;
+        }
+
+        private boolean isCurrentPlatform(Path p) {
+            Path jh = Paths.get(System.getProperty("java.home"));
+            try {
+                return Files.isSameFile(p, jh);
+            } catch (IOException ex) {
+                throw new IllegalArgumentException(p.toString(), ex);
+            }
+        }
+
+        @Override
+        Location getModuleLocation(String name) throws IOException {
+            initSystemModules();
+            return systemModules.get(name);
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() throws IOException {
+            initSystemModules();
+            Set<Location> locns = new LinkedHashSet<>();
+            for (Location l: systemModules.values())
+                locns.add(l);
+            return Collections.singleton(locns);
+        }
+
+        private void initSystemModules() throws IOException {
+            if (systemModules != null) {
+                return;
+            }
+
+            if (javaHome == null) {
+                systemModules = Collections.emptyMap();
+                return;
+            }
+
+            if (modules == null) {
+                try {
+                    URI jrtURI = URI.create("jrt:/");
+                    FileSystem jrtfs;
+
+                    if (isCurrentPlatform(javaHome)) {
+                        jrtfs = FileSystems.getFileSystem(jrtURI);
+                    } else {
+                        try {
+                            Map<String, String> attrMap =
+                                    Collections.singletonMap("java.home", javaHome.toString());
+                            jrtfs = FileSystems.newFileSystem(jrtURI, attrMap);
+                        } catch (ProviderNotFoundException ex) {
+                            URL javaHomeURL = javaHome.resolve("jrt-fs.jar").toUri().toURL();
+                            ClassLoader currentLoader = Locations.class.getClassLoader();
+                            URLClassLoader fsLoader =
+                                    new URLClassLoader(new URL[] {javaHomeURL}, currentLoader);
+
+                            jrtfs = FileSystems.newFileSystem(jrtURI, Collections.emptyMap(), fsLoader);
+
+                            closeables.add(fsLoader);
+                        }
+
+                        closeables.add(jrtfs);
+                    }
+
+                    modules = jrtfs.getPath("/modules");
+                } catch (FileSystemNotFoundException | ProviderNotFoundException e) {
+                    modules = javaHome.resolve("modules");
+                    if (!Files.exists(modules))
+                        throw new IOException("can't find system classes", e);
+                }
+            }
+
+            systemModules = new LinkedHashMap<>();
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules, Files::isDirectory)) {
+                for (Path entry : stream) {
+                    String moduleName = entry.getFileName().toString();
+                    String name = location.getName() + "[" + moduleName + "]";
+                    ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName,
+                            Collections.singleton(entry), false, true);
+                    systemModules.put(moduleName, h);
+                }
+            }
+        }
+    }
+
     Map<Location, LocationHandler> handlersForLocation;
     Map<Option, LocationHandler> handlersForOption;
 
@@ -722,17 +1498,23 @@
         handlersForLocation = new HashMap<>();
         handlersForOption = new EnumMap<>(Option.class);
 
-        LocationHandler[] handlers = {
+        BasicLocationHandler[] handlers = {
             new BootClassPathLocationHandler(),
             new ClassPathLocationHandler(),
             new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH),
             new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH),
-            new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), Option.D),
-            new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S),
-            new OutputLocationHandler((StandardLocation.NATIVE_HEADER_OUTPUT), Option.H)
+            new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSORMODULEPATH),
+            new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
+            new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
+            new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
+            new ModuleSourcePathLocationHandler(),
+            // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES?
+            new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADEMODULEPATH),
+            new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULEPATH, Option.MP),
+            new SystemModulesLocationHandler(),
         };
 
-        for (LocationHandler h : handlers) {
+        for (BasicLocationHandler h : handlers) {
             handlersForLocation.put(h.location, h);
             for (Option o : h.options) {
                 handlersForOption.put(o, h);
@@ -740,14 +1522,56 @@
         }
     }
 
+    private SearchPath moduleOverrideSearchPath; // for old style patch option; retained for transition
+    private Map<String, SearchPath> patchMap;
+
     boolean handleOption(Option option, String value) {
-        LocationHandler h = handlersForOption.get(option);
-        return (h == null ? false : h.handleOption(option, value));
+        switch (option) {
+            case XPATCH:
+                if (value.contains("=")) {
+                    Map<String, SearchPath> map = new LinkedHashMap<>();
+                    for (String entry: value.split(",")) {
+                        int eq = entry.indexOf('=');
+                        if (eq > 0) {
+                            String mName = entry.substring(0, eq);
+                            SearchPath mPatchPath = new SearchPath()
+                                    .addFiles(entry.substring(eq + 1));
+                            boolean ok = true;
+                            for (Path p: mPatchPath) {
+                                Path mi = p.resolve("module-info.class");
+                                if (Files.exists(mi)) {
+                                    log.error(Errors.LocnModuleInfoNotAllowedOnPatchPath(mi));
+                                    ok = false;
+                                }
+                            }
+                            if (ok && !mPatchPath.isEmpty()) {
+                                map.computeIfAbsent(mName, (_x) -> new SearchPath())
+                                        .addAll(mPatchPath);
+                            }
+                        } else {
+                            log.error(Errors.LocnInvalidArgForXpatch(entry));
+                        }
+                    }
+                    patchMap = map;
+                } else {
+                     // for old style patch option; retained for transition
+                    moduleOverrideSearchPath = new SearchPath().addFiles(value);
+                }
+                return true;
+            default:
+                LocationHandler h = handlersForOption.get(option);
+                return (h == null ? false : h.handleOption(option, value));
+        }
+    }
+
+    boolean hasLocation(Location location) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? false : h.isSet());
     }
 
     Collection<Path> getLocation(Location location) {
         LocationHandler h = getHandler(location);
-        return (h == null ? null : h.getLocation());
+        return (h == null ? null : h.getPaths());
     }
 
     Path getOutputLocation(Location location) {
@@ -768,12 +1592,34 @@
             }
             handlersForLocation.put(location, h);
         }
-        h.setLocation(files);
+        h.setPaths(files);
+    }
+
+    Location getModuleLocation(Location location, String name) throws IOException {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.getModuleLocation(name));
+    }
+
+    Location getModuleLocation(Location location, Path dir) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.getModuleLocation(dir));
+    }
+
+    String inferModuleName(Location location) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.inferModuleName());
+    }
+
+    Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.listModuleLocations());
     }
 
     protected LocationHandler getHandler(Location location) {
         Objects.requireNonNull(location);
-        return handlersForLocation.get(location);
+        return (location instanceof LocationHandler)
+                ? (LocationHandler) location
+                : handlersForLocation.get(location);
     }
 
     /**
@@ -785,4 +1631,12 @@
                 && (n.endsWith(".jar") || n.endsWith(".zip"));
     }
 
+    static Path normalize(Path p) {
+        try {
+            return p.toRealPath();
+        } catch (IOException e) {
+            return p.toAbsolutePath().normalize();
+        }
+    }
+
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ModuleNameReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ModuleNameReader.java
new file mode 100644
index 0000000..558be48
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ModuleNameReader.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.javac.file;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.sun.tools.javac.jvm.ClassFile;
+
+import static com.sun.tools.javac.jvm.ClassFile.*;
+
+
+/**
+ * Stripped down ClassReader, just sufficient to read module names from module-info.class files
+ * while analyzing the module path.
+ *
+ * <p>
+ * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
+ * your own risk. This code and its internal interfaces are subject to change or deletion without
+ * notice.</b>
+ */
+public class ModuleNameReader {
+    static class BadClassFile extends Exception {
+        private static final long serialVersionUID = 0;
+        BadClassFile(String msg) {
+            super(msg);
+        }
+    }
+
+    private static final int INITIAL_BUFFER_SIZE = 0x0fff0;
+
+    /** The buffer containing the currently read class file.
+     */
+    private byte[] buf = new byte[INITIAL_BUFFER_SIZE];
+
+    /** The current input pointer.
+     */
+    private int bp;
+
+    /** The objects of the constant pool.
+     */
+    private Object[] poolObj;
+
+    /** For every constant pool entry, an index into buf where the
+     *  defining section of the entry is found.
+     */
+    private int[] poolIdx;
+
+    ModuleNameReader() {
+    }
+
+    String readModuleName(Path p) throws IOException, BadClassFile {
+        try (InputStream in = Files.newInputStream(p)) {
+            bp = 0;
+            buf = readInputStream(buf, in);
+
+            int magic = nextInt();
+            if (magic != JAVA_MAGIC)
+                throw new BadClassFile("illegal.start.of.class.file");
+
+            int minorVersion = nextChar();
+            int majorVersion = nextChar();
+
+            indexPool();
+
+            int accessflags = nextChar();
+            return readModuleInfoName(nextChar());
+        }
+    }
+
+    /** Extract a character at position bp from buf.
+     */
+    char getChar(int bp) {
+        return
+            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
+    }
+
+    /** Read a character.
+     */
+    char nextChar() {
+        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
+    }
+
+    /** Read an integer.
+     */
+    int nextInt() {
+        return
+            ((buf[bp++] & 0xFF) << 24) +
+            ((buf[bp++] & 0xFF) << 16) +
+            ((buf[bp++] & 0xFF) << 8) +
+            (buf[bp++] & 0xFF);
+    }
+
+    /** Index all constant pool entries, writing their start addresses into
+     *  poolIdx.
+     */
+    void indexPool() throws BadClassFile {
+        poolIdx = new int[nextChar()];
+        poolObj = new Object[poolIdx.length];
+        int i = 1;
+        while (i < poolIdx.length) {
+            poolIdx[i++] = bp;
+            byte tag = buf[bp++];
+            switch (tag) {
+            case CONSTANT_Utf8: case CONSTANT_Unicode: {
+                int len = nextChar();
+                bp = bp + len;
+                break;
+            }
+            case CONSTANT_Class:
+            case CONSTANT_String:
+            case CONSTANT_MethodType:
+                bp = bp + 2;
+                break;
+            case CONSTANT_MethodHandle:
+                bp = bp + 3;
+                break;
+            case CONSTANT_Fieldref:
+            case CONSTANT_Methodref:
+            case CONSTANT_InterfaceMethodref:
+            case CONSTANT_NameandType:
+            case CONSTANT_Integer:
+            case CONSTANT_Float:
+            case CONSTANT_InvokeDynamic:
+                bp = bp + 4;
+                break;
+            case CONSTANT_Long:
+            case CONSTANT_Double:
+                bp = bp + 8;
+                i++;
+                break;
+            default:
+                throw new BadClassFile("malformed constant pool");
+            }
+        }
+    }
+
+    /** Read the class name of a module-info.class file.
+     * The name is stored in a CONSTANT_Class entry, where the
+     * class name is of the form module-name/module-info.
+     */
+    String readModuleInfoName(int i) throws BadClassFile {
+        int classIndex = poolIdx[i];
+        if (buf[classIndex] == CONSTANT_Class) {
+            int utf8Index = poolIdx[getChar(classIndex + 1)];
+            if (buf[utf8Index] == CONSTANT_Utf8) {
+                int len = getChar(utf8Index + 1);
+                int start = utf8Index + 3;
+                String suffix = "/module-info";
+                if (endsWith(buf, start, len, suffix))
+                    return new String(ClassFile.internalize(buf, start, len - suffix.length()));
+            }
+        }
+        throw new BadClassFile("bad module-info name");
+    }
+
+    private boolean endsWith(byte[] buf, int start, int len, String suffix) {
+        if (len <= suffix.length())
+            return false;
+        for (int i = 0; i < suffix.length(); i++) {
+            if (buf[start + len - suffix.length() + i] != suffix.charAt(i))
+                return false;
+        }
+        return true;
+    }
+
+    private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
+        try {
+            buf = ensureCapacity(buf, s.available());
+            int r = s.read(buf);
+            int bp = 0;
+            while (r != -1) {
+                bp += r;
+                buf = ensureCapacity(buf, bp);
+                r = s.read(buf, bp, buf.length - bp);
+            }
+            return buf;
+        } finally {
+            try {
+                s.close();
+            } catch (IOException e) {
+                /* Ignore any errors, as this stream may have already
+                 * thrown a related exception which is the one that
+                 * should be reported.
+                 */
+            }
+        }
+    }
+
+    /*
+     * ensureCapacity will increase the buffer as needed, taking note that
+     * the new buffer will always be greater than the needed and never
+     * exactly equal to the needed size or bp. If equal then the read (above)
+     * will infinitely loop as buf.length - bp == 0.
+     */
+    private static byte[] ensureCapacity(byte[] buf, int needed) {
+        if (buf.length <= needed) {
+            byte[] old = buf;
+            buf = new byte[Integer.highestOneBit(needed) << 1];
+            System.arraycopy(old, 0, buf, 0, old.length);
+        }
+        return buf;
+    }
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
index 60f12fc..3ef115f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
@@ -107,9 +107,8 @@
         V49(49, 0),   // JDK 1.5: enum, generics, annotations
         V50(50, 0),   // JDK 1.6: stackmaps
         V51(51, 0),   // JDK 1.7
-        V52(52, 0);   // JDK 1.8: lambda, type annos, param names
-        // JDK9 still marked as V52 // V53(53, 0);   // JDK 1.9
-
+        V52(52, 0),   // JDK 1.8: lambda, type annos, param names
+        V53(52, 0);   // JDK 1.9: modules  **** FIXME TO 53 BEFORE RELEASE *****
         Version(int major, int minor) {
             this.major = major;
             this.minor = minor;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
index 0d0ca8a..56bca42 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
@@ -44,6 +44,7 @@
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Directive.*;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
@@ -100,6 +101,10 @@
      */
     boolean allowSimplifiedVarargs;
 
+    /** Switch: allow modules.
+     */
+    boolean allowModules;
+
    /** Lint option: warn about classfile issues
      */
     boolean lintClassfile;
@@ -137,6 +142,9 @@
      */
     protected WriteableScope typevars;
 
+    private List<InterimUsesDirective> interimUses = List.nil();
+    private List<InterimProvidesDirective> interimProvides = List.nil();
+
     /** The path name of the class file currently being read.
      */
     protected JavaFileObject currentClassFile = null;
@@ -145,6 +153,10 @@
      */
     protected Symbol currentOwner = null;
 
+    /** The module containing the class currently being read.
+     */
+    protected ModuleSymbol currentModule = null;
+
     /** The buffer containing the currently read class file.
      */
     byte[] buf = new byte[INITIAL_BUFFER_SIZE];
@@ -228,6 +240,7 @@
 
         Source source = Source.instance(context);
         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
+        allowModules     = source.allowModules();
 
         saveParameterNames = options.isSet("save-parameter-names");
 
@@ -478,7 +491,7 @@
         // simplified to (buf[start] == '[')
         return (buf[start] == '[' || buf[start + len - 1] == ';')
             ? (Object)sigToType(buf, start, len)
-            : (Object)syms.enterClass(names.fromUtf(internalize(buf, start,
+            : (Object)enterClass(names.fromUtf(internalize(buf, start,
                                                            len)));
     }
 
@@ -500,6 +513,23 @@
         return (ClassSymbol)obj;
     }
 
+    Name readClassName(int i) {
+        int index = poolIdx[i];
+        if (index == 0) return null;
+        byte tag = buf[index];
+        if (tag != CONSTANT_Class) {
+            throw badClassFile("bad.const.pool.entry",
+                               currentClassFile.toString(),
+                               "CONSTANT_Class_info", i);
+        }
+        int nameIndex =  poolIdx[getChar(index + 1)];
+        int len = getChar(nameIndex + 1);
+        int start = nameIndex + 3;
+        if (buf[start] == '[' || buf[start + len - 1] == ';')
+            throw badClassFile("wrong class name"); //TODO: proper diagnostics
+        return names.fromUtf(internalize(buf, start, len));
+    }
+
     /** Read name.
      */
     Name readName(int i) {
@@ -522,6 +552,34 @@
         return (NameAndType)obj;
     }
 
+    /** Read the class name of a module-info.class file.
+     * The name is stored in a CONSTANT_Class entry, where the
+     * class name is of the form module-name.module-info.
+     */
+    Name readModuleInfoName(int i) {
+        int classIndex = poolIdx[i];
+        if (buf[classIndex] == CONSTANT_Class) {
+            int utf8Index = poolIdx[getChar(classIndex + 1)];
+            if (buf[utf8Index] == CONSTANT_Utf8) {
+                int len = getChar(utf8Index + 1);
+                int start = utf8Index + 3;
+                return names.fromUtf(internalize(buf, start, len));
+            }
+        }
+        throw badClassFile("bad.module-info.name");
+    }
+
+    /** Read requires_flags.
+     */
+    Set<RequiresFlag> readRequiresFlags(int flags) {
+        Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class);
+        for (RequiresFlag f: RequiresFlag.values()) {
+            if ((flags & f.value) != 0)
+                set.add(f);
+        }
+        return set;
+    }
+
 /************************************************************************
  * Reading Types
  ***********************************************************************/
@@ -660,7 +718,7 @@
             switch (c) {
 
             case ';': {         // end
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
 
@@ -674,7 +732,7 @@
             }
 
             case '<':           // generic arguments
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
                 outer = new ClassType(outer, sigToTypes('>'), t) {
@@ -737,7 +795,7 @@
             case '.':
                 //we have seen an enclosing non-generic class
                 if (outer != Type.noType) {
-                    t = syms.enterClass(names.fromUtf(signatureBuffer,
+                    t = enterClass(names.fromUtf(signatureBuffer,
                                                  startSbp,
                                                  sbp - startSbp));
                     outer = new ClassType(outer, List.<Type>nil(), t);
@@ -941,7 +999,12 @@
             new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     ClassSymbol c = (ClassSymbol) sym;
-                    readInnerClasses(c);
+                    if (currentModule.module_info == c) {
+                        //prevent entering the classes too soon:
+                        skipInnerClasses();
+                    } else {
+                        readInnerClasses(c);
+                    }
                 }
             },
 
@@ -981,25 +1044,6 @@
                 }
             },
 
-            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
-                protected void read(Symbol sym, int attrlen) {
-                    int newbp = bp + attrlen;
-                    if (saveParameterNames) {
-                        sawMethodParameters = true;
-                        int numEntries = nextByte();
-                        parameterNameIndices = new int[numEntries];
-                        haveParameterNameIndices = true;
-                        for (int i = 0; i < numEntries; i++) {
-                            int nameIndex = nextChar();
-                            int flags = nextChar();
-                            parameterNameIndices[i] = nameIndex;
-                        }
-                    }
-                    bp = newbp;
-                }
-            },
-
-
             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     ClassSymbol c = (ClassSymbol) sym;
@@ -1130,12 +1174,109 @@
                 }
             },
 
-
             // The following attributes for a Code attribute are not currently handled
             // StackMapTable
             // SourceDebugExtension
             // LineNumberTable
             // LocalVariableTypeTable
+
+            // standard v52 attributes
+
+            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
+                protected void read(Symbol sym, int attrlen) {
+                    int newbp = bp + attrlen;
+                    if (saveParameterNames) {
+                        sawMethodParameters = true;
+                        int numEntries = nextByte();
+                        parameterNameIndices = new int[numEntries];
+                        haveParameterNameIndices = true;
+                        for (int i = 0; i < numEntries; i++) {
+                            int nameIndex = nextChar();
+                            int flags = nextChar();
+                            parameterNameIndices[i] = nameIndex;
+                        }
+                    }
+                    bp = newbp;
+                }
+            },
+
+            // standard v53 attributes
+
+            new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) {
+                @Override
+                protected boolean accepts(AttributeKind kind) {
+                    return super.accepts(kind) && allowModules;
+                }
+                protected void read(Symbol sym, int attrLen) {
+                    if (sym.kind == TYP && sym.owner.kind == MDL) {
+                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
+                        ListBuffer<Directive> directives = new ListBuffer<>();
+
+                        ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+                        int nrequires = nextChar();
+                        for (int i = 0; i < nrequires; i++) {
+                            Name name = readName(nextChar());
+                            ModuleSymbol rsym = syms.enterModule(name);
+                            Set<RequiresFlag> flags = readRequiresFlags(nextChar());
+                            requires.add(new RequiresDirective(rsym, flags));
+                        }
+                        msym.requires = requires.toList();
+                        directives.addAll(msym.requires);
+
+                        ListBuffer<ExportsDirective> exports = new ListBuffer<>();
+                        int nexports = nextChar();
+                        for (int i = 0; i < nexports; i++) {
+                            Name n = readName(nextChar());
+                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+                            int nto = nextChar();
+                            List<ModuleSymbol> to;
+                            if (nto == 0) {
+                                to = null;
+                            } else {
+                                ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
+                                for (int t = 0; t < nto; t++)
+                                    lb.append(syms.enterModule(readName(nextChar())));
+                                to = lb.toList();
+                            }
+                            exports.add(new ExportsDirective(p, to));
+                        }
+                        msym.exports = exports.toList();
+                        directives.addAll(msym.exports);
+
+                        msym.directives = directives.toList();
+
+                        ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
+                        int nuses = nextChar();
+                        for (int i = 0; i < nuses; i++) {
+                            Name srvc = readClassName(nextChar());
+                            uses.add(new InterimUsesDirective(srvc));
+                        }
+                        interimUses = uses.toList();
+
+                        ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
+                        int nprovides = nextChar();
+                        for (int i = 0; i < nprovides; i++) {
+                            Name srvc = readClassName(nextChar());
+                            Name impl = readClassName(nextChar());
+                            provides.add(new InterimProvidesDirective(srvc, impl));
+                        }
+                        interimProvides = provides.toList();
+                    }
+                }
+            },
+
+            new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) {
+                @Override
+                protected boolean accepts(AttributeKind kind) {
+                    return super.accepts(kind) && allowModules;
+                }
+                protected void read(Symbol sym, int attrLen) {
+                    if (sym.kind == TYP && sym.owner.kind == MDL) {
+                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
+                        msym.version = readName(nextChar());
+                    }
+                }
+            },
         };
 
         for (AttributeReader r: readers)
@@ -1388,7 +1529,7 @@
         int index = poolIdx[i];
         int length = getChar(index + 1);
         if (buf[index + length + 2] != ';')
-            return syms.enterClass(readName(i)).type;
+            return enterClass(readName(i)).type;
         return readType(i);
     }
 
@@ -2175,6 +2316,16 @@
         }
     }
 
+    void skipInnerClasses() {
+        int n = nextChar();
+        for (int i = 0; i < n; i++) {
+            nextChar();
+            nextChar();
+            nextChar();
+            nextChar();
+        }
+    }
+
     /** Enter type variables of this classtype and all enclosing ones in
      *  `typevars'.
      */
@@ -2193,6 +2344,14 @@
         enterTypevars(sym.type);
     }
 
+    protected ClassSymbol enterClass(Name name) {
+        return syms.enterClass(currentModule, name);
+    }
+
+    protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
+        return syms.enterClass(currentModule, name, owner);
+    }
+
     /** Read contents of a given class symbol `c'. Both external and internal
      *  versions of an inner class are read.
      */
@@ -2208,14 +2367,27 @@
             enterTypevars(ct.getEnclosingType());
 
         // read flags, or skip if this is an inner class
-        long flags = adjustClassFlags(nextChar());
-        if (c.owner.kind == PCK) c.flags_field = flags;
-
-        // read own class name and check that it matches
-        ClassSymbol self = readClassSymbol(nextChar());
-        if (c != self)
-            throw badClassFile("class.file.wrong.class",
-                               self.flatname);
+        long f = nextChar();
+        long flags = adjustClassFlags(f);
+        if ((flags & MODULE) == 0) {
+            if (c.owner.kind == PCK) c.flags_field = flags;
+            // read own class name and check that it matches
+            currentModule = c.packge().modle;
+            ClassSymbol self = readClassSymbol(nextChar());
+            if (c != self) {
+                throw badClassFile("class.file.wrong.class",
+                                   self.flatname);
+            }
+        } else {
+            c.flags_field = flags;
+            Name modInfoName = readModuleInfoName(nextChar());
+            if (c.owner.name == null) {
+                syms.enterModule((ModuleSymbol) c.owner, Convert.packagePart(modInfoName));
+            } else {
+                // TODO: validate name
+            }
+            currentModule = (ModuleSymbol) c.owner;
+        }
 
         // class attributes must be read before class
         // skip ahead to read class attributes
@@ -2272,7 +2444,7 @@
             if (outer != null) { // we have a member class
                 if (name == names.empty)
                     name = names.one;
-                ClassSymbol member = syms.enterClass(name, outer);
+                ClassSymbol member = enterClass(name, outer);
                 if ((flags & STATIC) == 0) {
                     ((ClassType)member.type).setEnclosingType(outer.type);
                     if (member.erasure_field != null)
@@ -2354,11 +2526,24 @@
             } else {
                 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType());
             }
+
+            if (c == currentModule.module_info) {
+                if (interimUses.nonEmpty() || interimProvides.nonEmpty()) {
+                    Assert.check(currentModule.isCompleted());
+                    currentModule.usesProvidesCompleter =
+                            new UsesProvidesCompleter(currentModule, interimUses, interimProvides);
+                } else {
+                    currentModule.uses = List.nil();
+                    currentModule.provides = List.nil();
+                }
+            }
         } catch (IOException ex) {
             throw badClassFile("unable.to.access.file", ex.getMessage());
         } catch (ArrayIndexOutOfBoundsException ex) {
             throw badClassFile("bad.class.file", c.flatname);
         } finally {
+            interimUses = List.nil();
+            interimProvides = List.nil();
             missingTypeVariables = List.nil();
             foundTypeVariables = List.nil();
             filling = false;
@@ -2429,6 +2614,10 @@
     }
 
     long adjustClassFlags(long flags) {
+        if ((flags & ACC_MODULE) != 0) {
+            flags &= ~ACC_MODULE;
+            flags |= MODULE;
+        }
         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
     }
 
@@ -2580,4 +2769,58 @@
             sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable);
         }
     }
+
+    private static final class InterimUsesDirective {
+        public final Name service;
+
+        public InterimUsesDirective(Name service) {
+            this.service = service;
+        }
+
+    }
+
+    private static final class InterimProvidesDirective {
+        public final Name service;
+        public final Name impl;
+
+        public InterimProvidesDirective(Name service, Name impl) {
+            this.service = service;
+            this.impl = impl;
+        }
+
+    }
+
+    private final class UsesProvidesCompleter implements Completer {
+        private final ModuleSymbol currentModule;
+        private final List<InterimUsesDirective> interimUsesCopy;
+        private final List<InterimProvidesDirective> interimProvidesCopy;
+
+        public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) {
+            this.currentModule = currentModule;
+            this.interimUsesCopy = interimUsesCopy;
+            this.interimProvidesCopy = interimProvidesCopy;
+        }
+
+        @Override
+        public void complete(Symbol sym) throws CompletionFailure {
+            ListBuffer<Directive> directives = new ListBuffer<>();
+            directives.addAll(currentModule.directives);
+            ListBuffer<UsesDirective> uses = new ListBuffer<>();
+            for (InterimUsesDirective interim : interimUsesCopy) {
+                UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service));
+                uses.add(d);
+                directives.add(d);
+            }
+            currentModule.uses = uses.toList();
+            ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
+            for (InterimProvidesDirective interim : interimProvidesCopy) {
+                ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
+                                                            syms.enterClass(currentModule, interim.impl));
+                provides.add(d);
+                directives.add(d);
+            }
+            currentModule.provides = provides.toList();
+            currentModule.directives = directives.toList();
+        }
+    }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
index aa161b5..3322d0f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
@@ -33,10 +33,12 @@
 
 import javax.tools.JavaFileManager;
 import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
+import com.sun.tools.javac.code.Directive.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Types.UniqueType;
@@ -97,6 +99,12 @@
     /** Type utilities. */
     private Types types;
 
+    /**
+     * If true, class files will be written in module-specific subdirectories
+     * of the CLASS_OUTPUT location.
+     */
+    public boolean multiModuleMode;
+
     /** The initial sizes of the data and constant pool buffers.
      *  Sizes are increased when buffers get full.
      */
@@ -935,6 +943,58 @@
     }
 
 /**********************************************************************
+ * Writing module attributes
+ **********************************************************************/
+
+    /** Write the Module attribute if needed.
+     *  Returns the number of attributes written (0 or 1).
+     */
+    int writeModuleAttribute(ClassSymbol c) {
+        ModuleSymbol m = (ModuleSymbol) c.owner;
+
+        int alenIdx = writeAttr(names.Module);
+        ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+        for (RequiresDirective r: m.requires) {
+            if (!r.flags.contains(RequiresFlag.EXTRA))
+                requires.add(r);
+        }
+        databuf.appendChar(requires.size());
+        for (RequiresDirective r: requires) {
+            databuf.appendChar(pool.put(r.module.name));
+            databuf.appendChar(RequiresFlag.value(r.flags));
+        }
+
+        List<ExportsDirective> exports = m.exports;
+        databuf.appendChar(exports.size());
+        for (ExportsDirective e: exports) {
+            databuf.appendChar(pool.put(names.fromUtf(externalize(e.packge.flatName()))));
+            if (e.modules == null) {
+                databuf.appendChar(0);
+            } else {
+                databuf.appendChar(e.modules.size());
+                for (ModuleSymbol msym: e.modules)
+                    databuf.appendChar(pool.put(msym.name));
+            }
+        }
+
+        List<UsesDirective> uses = m.uses;
+        databuf.appendChar(uses.size());
+        for (UsesDirective s: uses) {
+            databuf.appendChar(pool.put(s.service));
+        }
+
+        List<ProvidesDirective> services = m.provides;
+        databuf.appendChar(services.size());
+        for (ProvidesDirective s: services) {
+            databuf.appendChar(pool.put(s.service));
+            databuf.appendChar(pool.put(s.impl));
+        }
+
+        endAttr(alenIdx);
+        return 1;
+    }
+
+/**********************************************************************
  * Writing Objects
  **********************************************************************/
 
@@ -1564,9 +1624,17 @@
     public JavaFileObject writeClass(ClassSymbol c)
         throws IOException, PoolOverflow, StringOverflow
     {
+        String name = (c.owner.kind == MDL ? c.name : c.flatname).toString();
+        Location outLocn;
+        if (multiModuleMode) {
+            ModuleSymbol msym = c.owner.kind == MDL ? (ModuleSymbol) c.owner : c.packge().modle;
+            outLocn = fileManager.getModuleLocation(CLASS_OUTPUT, msym.name.toString());
+        } else {
+            outLocn = CLASS_OUTPUT;
+        }
         JavaFileObject outFile
-            = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
-                                               c.flatname.toString(),
+            = fileManager.getJavaFileForOutput(outLocn,
+                                               name,
                                                JavaFileObject.Kind.CLASS,
                                                c.sourcefile);
         OutputStream out = outFile.openOutputStream();
@@ -1604,11 +1672,17 @@
         List<Type> interfaces = types.interfaces(c.type);
         List<Type> typarams = c.type.getTypeArguments();
 
-        int flags = adjustFlags(c.flags() & ~DEFAULT);
-        if ((flags & PROTECTED) != 0) flags |= PUBLIC;
-        flags = flags & ClassFlags & ~STRICTFP;
-        if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
-        if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL;
+        int flags;
+        if (c.owner.kind == MDL) {
+            flags = ACC_MODULE;
+        } else {
+            flags = adjustFlags(c.flags() & ~DEFAULT);
+            if ((flags & PROTECTED) != 0) flags |= PUBLIC;
+            flags = flags & ClassFlags & ~STRICTFP;
+            if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
+            if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL;
+        }
+
         if (dumpClassModifiers) {
             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
             pw.println();
@@ -1693,6 +1767,9 @@
         acount += writeJavaAnnotations(c.getRawAttributes());
         acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
         acount += writeEnclosingMethodAttribute(c);
+        if (c.owner.kind == MDL) {
+            acount += writeModuleAttribute(c);
+        }
         acount += writeExtraClassAttributes(c);
 
         poolbuf.appendInt(JAVA_MAGIC);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java
index 38f1134..31cbda2 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -33,12 +33,14 @@
 
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
 import com.sun.tools.javac.code.Attribute;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
@@ -82,6 +84,12 @@
      */
     private boolean checkAll;
 
+    /**
+     * If true, class files will be written in module-specific subdirectories
+     * of the NATIVE_HEADER_OUTPUT location.
+     */
+    public boolean multiModuleMode;
+
     private Context context;
 
     private static final boolean isWindows =
@@ -168,8 +176,15 @@
      */
     public FileObject write(ClassSymbol c) throws IOException {
         String className = c.flatName().toString();
+        Location outLocn;
+        if (multiModuleMode) {
+            ModuleSymbol msym = c.owner.kind == MDL ? (ModuleSymbol) c.owner : c.packge().modle;
+            outLocn = fileManager.getModuleLocation(StandardLocation.NATIVE_HEADER_OUTPUT, msym.name.toString());
+        } else {
+            outLocn = StandardLocation.NATIVE_HEADER_OUTPUT;
+        }
         FileObject outFile
-            = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
+            = fileManager.getFileForOutput(outLocn,
                 "", className.replaceAll("[.$]", "_") + ".h", null);
         PrintWriter out = new PrintWriter(outFile.openWriter());
         try {
@@ -675,5 +690,10 @@
         public R visitType(Type t, P p) {
             return defaultAction(t, p);
         }
+
+        @Override
+        public R visitModuleType(Type.ModuleType t, P p) {
+            return defaultAction(t, p);
+        }
     }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
index 5d79556..ea5d075 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
@@ -29,17 +29,24 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
 
@@ -53,6 +60,8 @@
 import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
 import com.sun.tools.javac.platform.PlatformDescription;
 import com.sun.tools.javac.platform.PlatformUtils;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
@@ -77,6 +86,7 @@
     private Set<Path> files;
     private Map<Option, String> deferredFileManagerOptions;
     private Set<JavaFileObject> fileObjects;
+    private boolean emptyAllowed;
     private final Options options;
 
     private JavaFileManager fileManager;
@@ -248,14 +258,12 @@
      */
     public Set<JavaFileObject> getFileObjects() {
         if (fileObjects == null) {
-            if (files == null) {
-                fileObjects = Collections.emptySet();
-            } else {
-                fileObjects = new LinkedHashSet<>();
-                JavacFileManager jfm = (JavacFileManager) getFileManager();
-                for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files))
-                    fileObjects.add(fo);
-            }
+            fileObjects = new LinkedHashSet<>();
+        }
+        if (files != null) {
+            JavacFileManager jfm = (JavacFileManager) getFileManager();
+            for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files))
+                fileObjects.add(fo);
         }
         return fileObjects;
     }
@@ -291,8 +299,10 @@
         checkOptionAllowed(platformString == null,
                 option -> error("err.release.bootclasspath.conflict", option.getText()),
                 Option.BOOTCLASSPATH, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
-                Option.XBOOTCLASSPATH_PREPEND, Option.ENDORSEDDIRS, Option.EXTDIRS, Option.SOURCE,
-                Option.TARGET);
+                Option.XBOOTCLASSPATH_PREPEND,
+                Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
+                Option.EXTDIRS, Option.DJAVA_EXT_DIRS,
+                Option.SOURCE, Option.TARGET);
 
         if (platformString != null) {
             PlatformDescription platformDescription = PlatformUtils.lookupPlatformDescription(platformString);
@@ -396,13 +406,53 @@
      *      ILLEGAL_STATE
      */
     public boolean validate() {
+        JavaFileManager fm = getFileManager();
+        if (options.isSet(Option.M)) {
+            if (!fm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                log.error(Errors.OutputDirMustBeSpecifiedWithDashMOption);
+            } else if (!fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
+                log.error(Errors.ModulesourcepathMustBeSpecifiedWithDashMOption);
+            } else {
+                java.util.List<String> modules = Arrays.asList(options.get(Option.M).split(","));
+                try {
+                    for (String module : modules) {
+                        Location sourceLoc = fm.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH, module);
+                        if (sourceLoc == null) {
+                            log.error(Errors.ModuleNotFoundInModuleSourcePath(module));
+                        } else {
+                            Location classLoc = fm.getModuleLocation(StandardLocation.CLASS_OUTPUT, module);
+
+                            for (JavaFileObject file : fm.list(sourceLoc, "", EnumSet.of(JavaFileObject.Kind.SOURCE), true)) {
+                                String className = fm.inferBinaryName(sourceLoc, file);
+                                JavaFileObject classFile = fm.getJavaFileForInput(classLoc, className, Kind.CLASS);
+
+                                if (classFile == null || classFile.getLastModified() < file.getLastModified()) {
+                                    if (fileObjects == null)
+                                        fileObjects = new HashSet<>();
+                                    fileObjects.add(file);
+                                }
+                            }
+                        }
+                    }
+                } catch (IOException ex) {
+                    log.printLines(PrefixKind.JAVAC, "msg.io");
+                    ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
+                    return false;
+                }
+            }
+        }
+
         if (isEmpty()) {
             // It is allowed to compile nothing if just asking for help or version info.
             // But also note that none of these options are supported in API mode.
             if (options.isSet(Option.HELP)
                 || options.isSet(Option.X)
                 || options.isSet(Option.VERSION)
-                || options.isSet(Option.FULLVERSION))
+                || options.isSet(Option.FULLVERSION)
+                || options.isSet(Option.M))
+                return true;
+
+            if (emptyAllowed)
                 return true;
 
             if (JavaCompiler.explicitAnnotationProcessingRequested(options)) {
@@ -423,6 +473,32 @@
             return false;
         }
 
+        // The following checks are to help avoid accidental confusion between
+        // directories of modules and exploded module directories.
+        if (fm instanceof StandardJavaFileManager) {
+            StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
+            if (sfm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                Path outDir = sfm.getLocationAsPaths(StandardLocation.CLASS_OUTPUT).iterator().next();
+                if (sfm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
+                    // multi-module mode
+                    if (Files.exists(outDir.resolve("module-info.class"))) {
+                        log.error(Errors.MultiModuleOutdirCannotBeExplodedModule(outDir));
+                    }
+                } else {
+                    // single-module or legacy mode
+                    boolean lintPaths = options.isUnset(Option.XLINT_CUSTOM,
+                            "-" + LintCategory.PATH.option);
+                    if (lintPaths) {
+                        Path outDirParent = outDir.getParent();
+                        if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
+                            log.warning(LintCategory.PATH, Warnings.OutdirIsInExplodedModule(outDir));
+                        }
+                    }
+                }
+            }
+        }
+
+
         String sourceString = options.get(Option.SOURCE);
         Source source = (sourceString != null)
                 ? Source.lookup(sourceString)
@@ -471,10 +547,13 @@
             }
         }
 
+        if (options.isSet(Option.SOURCEPATH) && options.isSet(Option.MODULESOURCEPATH)) {
+            error("err.sourcepath.modulesourcepath.conflict");
+        }
+
         boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
 
         if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
-            JavaFileManager fm = getFileManager();
             if (fm instanceof BaseFileManager) {
                 if (((BaseFileManager) fm).isDefaultBootClassPath())
                     log.warning(LintCategory.OPTIONS, "source.no.bootclasspath", source.name);
@@ -484,22 +563,106 @@
         boolean obsoleteOptionFound = false;
 
         if (source.compareTo(Source.MIN) < 0) {
-            log.error("option.removed.source", source.name, Source.MIN.name);
+            log.error(Errors.OptionRemovedSource(source.name, Source.MIN.name));
         } else if (source == Source.MIN && lintOptions) {
-            log.warning(LintCategory.OPTIONS, "option.obsolete.source", source.name);
+            log.warning(LintCategory.OPTIONS, Warnings.OptionObsoleteSource(source.name));
             obsoleteOptionFound = true;
         }
 
         if (target.compareTo(Target.MIN) < 0) {
-            log.error("option.removed.target", target.name, Target.MIN.name);
+            log.error(Errors.OptionRemovedTarget(target.name, Target.MIN.name));
         } else if (target == Target.MIN && lintOptions) {
-            log.warning(LintCategory.OPTIONS, "option.obsolete.target", target.name);
+            log.warning(LintCategory.OPTIONS, Warnings.OptionObsoleteTarget(target.name));
             obsoleteOptionFound = true;
         }
 
+        final Target t = target;
+        checkOptionAllowed(t.compareTo(Target.JDK1_8) <= 0,
+                option -> error("err.option.not.allowed.with.target", option.getText(), t.name),
+                Option.BOOTCLASSPATH,
+                Option.XBOOTCLASSPATH_PREPEND, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
+                Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
+                Option.EXTDIRS, Option.DJAVA_EXT_DIRS);
+
+        checkOptionAllowed(t.compareTo(Target.JDK1_9) >= 0,
+                option -> error("err.option.not.allowed.with.target", option.getText(), t.name),
+                Option.MODULESOURCEPATH, Option.UPGRADEMODULEPATH,
+                Option.SYSTEM, Option.MODULEPATH, Option.ADDMODS, Option.LIMITMODS,
+                Option.XPATCH);
+
+        if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
+            if (!options.isSet(Option.PROC, "only")
+                    && !fm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                log.error(Errors.NoOutputDir);
+            }
+            if (options.isSet(Option.XMODULE)) {
+                log.error(Errors.XmoduleNoModuleSourcepath);
+            }
+        }
+
+        if (fm.hasLocation(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH) &&
+            fm.hasLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH)) {
+            log.error(Errors.ProcessorpathNoProcessormodulepath);
+        }
+
         if (obsoleteOptionFound)
             log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
 
+        String addExports = options.get(Option.XADDEXPORTS);
+        if (addExports != null) {
+            // Each entry must be of the form module/package=target-list where target-list is a
+            // comma-separated list of module or ALL-UNNAMED.
+            // All module/package pairs must be unique.
+            Pattern p = Pattern.compile("([^/]+)/([^=]+)=(.*)");
+            Map<String,List<String>> map = new LinkedHashMap<>();
+            for (String e: addExports.split("\0")) {
+                Matcher m = p.matcher(e);
+                if (!m.matches()) {
+                    log.error(Errors.XaddexportsMalformedEntry(e));
+                    continue;
+                }
+                String eModule = m.group(1);  // TODO: check a valid dotted identifier
+                String ePackage = m.group(2); // TODO: check a valid dotted identifier
+                String eTargets = m.group(3);  // TODO: check a valid list of dotted identifier or ALL-UNNAMED
+                String eModPkg = eModule + '/' + ePackage;
+                List<String> l = map.get(eModPkg);
+                map.put(eModPkg, (l == null) ? List.of(eTargets) : l.prepend(eTargets));
+            }
+            map.forEach((key, value) -> {
+                if (value.size() > 1) {
+                    log.error(Errors.XaddexportsTooMany(key));
+                    // TODO: consider adding diag fragments for the entries
+                }
+            });
+        }
+
+        String addReads = options.get(Option.XADDREADS);
+        if (addReads != null) {
+            // Each entry must be of the form module=source-list where source-list is a
+            // comma separated list of module or ALL-UNNAMED.
+            // All target modules (i.e. on left of '=')  must be unique.
+            Pattern p = Pattern.compile("([^=]+)=(.*)");
+            Map<String,List<String>> map = new LinkedHashMap<>();
+            for (String e: addReads.split("\0")) {
+                Matcher m = p.matcher(e);
+                if (!m.matches()) {
+                    log.error(Errors.XaddreadsMalformedEntry(e));
+                    continue;
+                }
+                String eModule = m.group(1);  // TODO: check a valid dotted identifier
+                String eSources = m.group(2);  // TODO: check a valid list of dotted identifier or ALL-UNNAMED
+                List<String> l = map.get(eModule);
+                map.put(eModule, (l == null) ? List.of(eSources) : l.prepend(eSources));
+            }
+            map.forEach((key, value) -> {
+                if (value.size() > 1) {
+                    log.error(Errors.XaddreadsTooMany(key));
+                    // TODO: consider adding diag fragments for the entries
+                }
+            });
+        }
+
+
         return !errors;
     }
 
@@ -513,6 +676,10 @@
                 && classNames.isEmpty();
     }
 
+    public void allowEmpty() {
+        this.emptyAllowed = true;
+    }
+
     /**
      * Gets the file manager options which may have been deferred
      * during processArgs.
@@ -626,6 +793,7 @@
     }
 
     private void report(String key, Object... args) {
+        // Would be good to have support for -XDrawDiagnostics here
         log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args));
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index 4d3bc8b..4e5f801 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -39,6 +39,7 @@
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ElementVisitor;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
@@ -67,12 +68,20 @@
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.JCDiagnostic.Factory;
 import com.sun.tools.javac.util.Log.WriterKind;
 
 import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+
 import static com.sun.tools.javac.code.TypeTag.CLASS;
 import static com.sun.tools.javac.main.Option.*;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
+
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 /** This class could be the main entry point for GJC when GJC is used as a
@@ -276,6 +285,18 @@
      */
     protected Flow flow;
 
+    /** The modules visitor
+     */
+    protected Modules modules;
+
+    /** The module finder
+     */
+    protected ModuleFinder moduleFinder;
+
+    /** The diagnostics factory
+     */
+    protected JCDiagnostic.Factory diags;
+
     /** The type eraser.
      */
     protected TransTypes transTypes;
@@ -336,6 +357,8 @@
      **/
     protected boolean implicitSourceFilesRead;
 
+    protected boolean enterDone;
+
     protected CompileStates compileStates;
 
     /** Construct a new compiler using a shared context.
@@ -382,6 +405,9 @@
         annotate = Annotate.instance(context);
         types = Types.instance(context);
         taskListener = MultiTaskListener.instance(context);
+        modules = Modules.instance(context);
+        moduleFinder = ModuleFinder.instance(context);
+        diags = Factory.instance(context);
 
         finder.sourceCompleter = sourceCompleter;
 
@@ -430,6 +456,18 @@
 
         if (platformProvider != null)
             closeables = closeables.prepend(platformProvider);
+
+        silentFail = new Symbol(ABSENT_TYP, 0, names.empty, Type.noType, syms.rootPackage) {
+            @DefinedBy(Api.LANGUAGE_MODEL)
+            public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+                return v.visitUnknown(this, p);
+            }
+            @Override
+            public boolean exists() {
+                return false;
+            }
+        };
+
     }
 
     /* Switches:
@@ -512,6 +550,11 @@
      */
     protected Set<JavaFileObject> inputFiles = new HashSet<>();
 
+    /** Used by the resolveBinaryNameOrIdent to say that the given type cannot be found, and that
+     *  an error has already been produced about that.
+     */
+    private final Symbol silentFail;
+
     protected boolean shouldStop(CompileState cs) {
         CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
             ? shouldStopPolicyIfError
@@ -625,18 +668,44 @@
      * @param name      The name to resolve
      */
     public Symbol resolveBinaryNameOrIdent(String name) {
+        ModuleSymbol msym;
+        String typeName;
+        int sep = name.indexOf('/');
+        if (sep == -1) {
+            msym = modules.getDefaultModule();
+            typeName = name;
+        } else if (source.allowModules() && !options.isSet("noModules")) {
+            Name modName = names.fromString(name.substring(0, sep));
+
+            msym = moduleFinder.findModule(modName);
+            typeName = name.substring(sep + 1);
+        } else {
+            log.error(Errors.InvalidModuleSpecifier(name));
+            return silentFail;
+        }
+
+        return resolveBinaryNameOrIdent(msym, typeName);
+    }
+
+    /** Resolve an identifier which may be the binary name of a class or
+     * the Java name of a class or package.
+     * @param msym      The module in which the search should be performed
+     * @param name      The name to resolve
+     */
+    public Symbol resolveBinaryNameOrIdent(ModuleSymbol msym, String name) {
         try {
             Name flatname = names.fromString(name.replace("/", "."));
-            return finder.loadClass(flatname);
+            return finder.loadClass(msym, flatname);
         } catch (CompletionFailure ignore) {
-            return resolveIdent(name);
+            return resolveIdent(msym, name);
         }
     }
 
     /** Resolve an identifier.
+     * @param msym      The module in which the search should be performed
      * @param name      The identifier to resolve
      */
-    public Symbol resolveIdent(String name) {
+    public Symbol resolveIdent(ModuleSymbol msym, String name) {
         if (name.equals(""))
             return syms.errSymbol;
         JavaFileObject prev = log.useSource(null);
@@ -650,7 +719,8 @@
             }
             JCCompilationUnit toplevel =
                 make.TopLevel(List.<JCTree>nil());
-            toplevel.packge = syms.unnamedPackage;
+            toplevel.modle = msym;
+            toplevel.packge = msym.unnamedPackage;
             return attr.attribIdent(tree, toplevel);
         } finally {
             log.useSource(prev);
@@ -737,6 +807,16 @@
             taskListener.started(e);
         }
 
+        // Process module declarations.
+        // If module resolution fails, ignore trees, and if trying to
+        // complete a specific symbol, throw CompletionFailure.
+        // Note that if module resolution failed, we may not even
+        // have enough modules available to access java.lang, and
+        // so risk getting FatalError("no.java.lang") from MemberEnter.
+        if (!modules.enter(List.of(tree), c)) {
+            throw new CompletionFailure(c, diags.fragment("cant.resolve.modules"));
+        }
+
         enter.complete(List.of(tree), c);
 
         if (!taskListener.isEmpty()) {
@@ -748,7 +828,16 @@
             boolean isPkgInfo =
                 tree.sourcefile.isNameCompatible("package-info",
                                                  JavaFileObject.Kind.SOURCE);
-            if (isPkgInfo) {
+            boolean isModuleInfo =
+                tree.sourcefile.isNameCompatible("module-info",
+                                                 JavaFileObject.Kind.SOURCE);
+            if (isModuleInfo) {
+                if (enter.getEnv(tree.modle) == null) {
+                    JCDiagnostic diag =
+                        diagFactory.fragment("file.does.not.contain.module");
+                    throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+                }
+            } else if (isPkgInfo) {
                 if (enter.getEnv(tree.packge) == null) {
                     JCDiagnostic diag =
                         diagFactory.fragment("file.does.not.contain.package",
@@ -812,8 +901,12 @@
 
             // These method calls must be chained to avoid memory leaks
             processAnnotations(
-                enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))),
-                classnames);
+                enterTrees(
+                        stopIfError(CompileState.PARSE,
+                                initModules(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))))
+                ),
+                classnames
+            );
 
             // If it's safe to do so, skip attr / flow / gen for implicit classes
             if (taskListener.isEmpty() &&
@@ -912,7 +1005,20 @@
     public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
        if (shouldStop(CompileState.ATTR))
            return List.nil();
-        return enterTrees(roots);
+        return enterTrees(initModules(roots));
+    }
+
+    public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
+        List<JCCompilationUnit> result = initModules(roots, null);
+        if (roots.isEmpty()) {
+            enterDone = true;
+        }
+        return result;
+    }
+
+    List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots, ClassSymbol c) {
+        modules.enter(roots, c);
+        return roots;
     }
 
     /**
@@ -931,6 +1037,8 @@
 
         enter.main(roots);
 
+        enterDone = true;
+
         if (!taskListener.isEmpty()) {
             for (JCCompilationUnit unit: roots) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
@@ -1085,7 +1193,8 @@
                         if (sym == null ||
                             (sym.kind == PCK && !processPcks) ||
                             sym.kind == ABSENT_TYP) {
-                            log.error("proc.cant.find.class", nameStr);
+                            if (sym != silentFail)
+                                log.error(Errors.ProcCantFindClass(nameStr));
                             errors = true;
                             continue;
                         }
@@ -1100,10 +1209,10 @@
                                 continue;
                             }
                             Assert.check(sym.kind == PCK);
-                            log.warning("proc.package.does.not.exist", nameStr);
+                            log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
                             pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
                         } catch (CompletionFailure e) {
-                            log.error("proc.cant.find.class", nameStr);
+                            log.error(Errors.ProcCantFindClass(nameStr));
                             errors = true;
                             continue;
                         }
@@ -1154,6 +1263,7 @@
         return
             options.isSet(PROCESSOR) ||
             options.isSet(PROCESSORPATH) ||
+            options.isSet(PROCESSORMODULEPATH) ||
             options.isSet(PROC, "only") ||
             options.isSet(XPRINT);
     }
@@ -1388,14 +1498,14 @@
             make.at(Position.FIRSTPOS);
             TreeMaker localMake = make.forToplevel(env.toplevel);
 
-            if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
+            if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
                 if (!(sourceOutput)) {
                     if (shouldStop(CompileState.LOWER))
-                       return;
-                    List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
-                    if (pdef.head != null) {
-                        Assert.check(pdef.tail.isEmpty());
-                        results.add(new Pair<>(env, (JCClassDecl)pdef.head));
+                        return;
+                    List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
+                    if (def.head != null) {
+                        Assert.check(def.tail.isEmpty());
+                        results.add(new Pair<>(env, (JCClassDecl)def.head));
                     }
                 }
                 return;
@@ -1589,6 +1699,10 @@
         }
     }
 
+    public boolean isEnterDone() {
+        return enterDone;
+    }
+
     /** Close the compiler, flushing the logs
      */
     public void close() {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
index 4d42113..187f6f7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
@@ -27,6 +27,7 @@
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.nio.file.NoSuchFileException;
@@ -144,7 +145,8 @@
             try {
                 // A fresh context was created above, so jfm must be a JavacFileManager
                 ((JavacFileManager)fileManager).close();
-            } catch (IOException ignore) {
+            } catch (IOException ex) {
+                bugMessage(ex);
             }
         }
         return result;
@@ -204,11 +206,13 @@
         if (batchMode)
             CacheFSInfo.preRegister(context);
 
+        boolean ok = true;
+
         // init file manager
         fileManager = context.get(JavaFileManager.class);
         if (fileManager instanceof BaseFileManager) {
             ((BaseFileManager) fileManager).setContext(context); // reinit with options
-            ((BaseFileManager) fileManager).handleOptions(args.getDeferredFileManagerOptions());
+            ok &= ((BaseFileManager) fileManager).handleOptions(args.getDeferredFileManagerOptions());
         }
 
         // handle this here so it works even if no other options given
@@ -219,7 +223,7 @@
             showClass(showClass);
         }
 
-        boolean ok = args.validate();
+        ok &= args.validate();
         if (!ok || log.nerrors > 0)
             return Result.CMDERR;
 
@@ -348,28 +352,28 @@
     void showClass(String className) {
         PrintWriter pw = log.getWriter(WriterKind.NOTICE);
         pw.println("javac: show class: " + className);
+
         URL url = getClass().getResource('/' + className.replace('.', '/') + ".class");
-        if (url == null)
-            pw.println("  class not found");
-        else {
+        if (url != null) {
             pw.println("  " + url);
-            try {
-                final String algorithm = "MD5";
-                byte[] digest;
-                MessageDigest md = MessageDigest.getInstance(algorithm);
-                try (DigestInputStream in = new DigestInputStream(url.openStream(), md)) {
-                    byte[] buf = new byte[8192];
-                    int n;
-                    do { n = in.read(buf); } while (n > 0);
-                    digest = md.digest();
-                }
-                StringBuilder sb = new StringBuilder();
-                for (byte b: digest)
-                    sb.append(String.format("%02x", b));
-                pw.println("  " + algorithm + " checksum: " + sb);
-            } catch (NoSuchAlgorithmException | IOException e) {
-                pw.println("  cannot compute digest: " + e);
+        }
+
+        try (InputStream in = getClass().getResourceAsStream('/' + className.replace('.', '/') + ".class")) {
+            final String algorithm = "MD5";
+            byte[] digest;
+            MessageDigest md = MessageDigest.getInstance(algorithm);
+            try (DigestInputStream din = new DigestInputStream(in, md)) {
+                byte[] buf = new byte[8192];
+                int n;
+                do { n = din.read(buf); } while (n > 0);
+                digest = md.digest();
             }
+            StringBuilder sb = new StringBuilder();
+            for (byte b: digest)
+                sb.append(String.format("%02x", b));
+            pw.println("  " + algorithm + " checksum: " + sb);
+        } catch (NoSuchAlgorithmException | IOException e) {
+            pw.println("  cannot compute digest: " + e);
         }
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
index b48f516..cddbda4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
@@ -184,6 +184,23 @@
 
     SOURCEPATH("-sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER),
 
+    MODULESOURCEPATH("-modulesourcepath", "opt.arg.mspath", "opt.modulesourcepath", STANDARD, FILEMANAGER),
+
+    MODULEPATH("-modulepath", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER),
+
+    MP("-mp", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER) {
+        @Override
+        public boolean process(OptionHelper helper, String option, String arg) {
+            return super.process(helper, "-modulepath", arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", "opt.arg.path", "opt.upgrademodulepath", STANDARD, FILEMANAGER),
+
+    SYSTEM("-system", "opt.arg.jdk", "opt.system", STANDARD, FILEMANAGER),
+
+    XPATCH("-Xpatch:", "opt.arg.path", "opt.Xpatch", EXTENDED, FILEMANAGER),
+
     BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) {
         @Override
         public boolean process(OptionHelper helper, String option, String arg) {
@@ -230,6 +247,8 @@
 
     PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER),
 
+    PROCESSORMODULEPATH("-processormodulepath", "opt.arg.path", "opt.processormodulepath", STANDARD, FILEMANAGER),
+
     PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC),
 
     D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
@@ -478,9 +497,9 @@
     PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) {
         @Override
         public boolean process(OptionHelper helper, String option) {
-            String p = option.substring(option.indexOf(':') + 1);
+            String p = option.substring(option.indexOf(':') + 1).trim();
             String prev = helper.get(PLUGIN);
-            helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p.trim());
+            helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p);
             return false;
         }
     },
@@ -507,6 +526,106 @@
         }
     },
 
+    XADDEXPORTS("-XaddExports:", "opt.arg.addExports", "opt.addExports", EXTENDED, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            if (option.matches(".*,.*=.*")) { // temporary, for backwards compatibility
+                return processOldStyle(helper, option);
+            }
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String prev = helper.get(XADDEXPORTS);
+            helper.put(XADDEXPORTS.text, (prev == null) ? p : prev + '\0' + p);
+            return false;
+        }
+
+        // convert old style option into a series of new-style options
+        private boolean processOldStyle(OptionHelper helper, String option) {
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String[] entries = p.split("[ ,]+");
+            Map<String, String> map = new LinkedHashMap<>();
+            for (String e: entries) {
+                // Each entry is of the form   module/package=target
+                // we must group values for the same module/package together
+                int eq = e.indexOf('=');
+                if (eq == -1) {
+                    // don't bother with error message for backwards compatible support
+                    continue;
+                }
+                String modPkg = e.substring(0, eq);
+                String target = e.substring(eq + 1);
+                String targets = map.get(modPkg);
+                map.put(modPkg, (targets == null) ? target : targets + "," + target);
+            }
+            boolean ok = true;
+            for (Map.Entry<String, String> e: map.entrySet()) {
+                // process as new-style options
+                String key = e.getKey();
+                String value = e.getValue();
+                ok = ok & process(helper, XADDEXPORTS.text + key + "=" + value);
+            };
+            return ok;
+        }
+    },
+
+    XADDREADS("-XaddReads:", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            if (option.matches(".*,.*=.*")) { // temporary, for backwards compatibility
+                return processOldStyle(helper, option);
+            }
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String prev = helper.get(XADDREADS);
+            helper.put(XADDREADS.text, (prev == null) ? p : prev + '\0' + p);
+            return false;
+        }
+
+        // convert old style option into a series of new-style options
+        private boolean processOldStyle(OptionHelper helper, String option) {
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String[] entries = p.split("[ ,]+");
+            Map<String, String> map = new LinkedHashMap<>();
+            for (String e: entries) {
+                // Each entry is of the form   module=target
+                // we must group values for the same module together
+                int eq = e.indexOf('=');
+                if (eq == -1) {
+                    // don't bother with error message for backwards compatible support
+                    continue;
+                }
+                String modPkg = e.substring(0, eq);
+                String target = e.substring(eq + 1);
+                String targets = map.get(modPkg);
+                map.put(modPkg, (targets == null) ? target : targets + "," + target);
+            }
+            boolean ok = true;
+            for (Map.Entry<String, String> e: map.entrySet()) {
+                // process as new-style options
+                String key = e.getKey();
+                String value = e.getValue();
+                ok = ok & process(helper, XADDEXPORTS.text + key + "=" + value);
+            };
+            return ok;
+        }
+    },
+
+    XMODULE("-Xmodule:", "opt.arg.module", "opt.module", EXTENDED, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            String prev = helper.get(XMODULE);
+            if (prev != null) {
+                helper.error("err.option.too.many", XMODULE.text);
+            }
+            String p = option.substring(option.indexOf(':') + 1);
+            helper.put(XMODULE.text, p);
+            return false;
+        }
+    },
+
+    M("-m", "opt.arg.m", "opt.m", STANDARD, BASIC),
+
+    ADDMODS("-addmods", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC),
+    LIMITMODS("-limitmods", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC),
+
     // This option exists only for the purpose of documenting itself.
     // It's actually implemented by the CommandLine class.
     AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) {
@@ -516,19 +635,19 @@
         }
     },
 
-    /*
-     * TODO: With apt, the matches method accepts anything if
-     * -XclassAsDecls is used; code elsewhere does the lookup to
-     * see if the class name is both legal and found.
-     *
-     * In apt, the process method adds the candidate class file
-     * name to a separate list.
-     */
+    // Standalone positional argument: source file or type name.
     SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
         @Override
         public boolean matches(String s) {
-            return s.endsWith(".java")  // Java source file
-                || SourceVersion.isName(s);   // Legal type name
+            if (s.endsWith(".java"))  // Java source file
+                return true;
+            int sep = s.indexOf('/');
+            if (sep != -1) {
+                return SourceVersion.isName(s.substring(0, sep))
+                        && SourceVersion.isName(s.substring(sep + 1));
+            } else {
+                return SourceVersion.isName(s);   // Legal type name
+            }
         }
         @Override
         public boolean process(OptionHelper helper, String option) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
index feb4f33..5ff7cb8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -34,6 +34,8 @@
 import javax.tools.JavaFileObject;
 import static javax.lang.model.util.ElementFilter.methodsIn;
 
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
@@ -52,6 +54,9 @@
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
+import com.sun.tools.javac.comp.CompileStates;
+import com.sun.tools.javac.comp.CompileStates.CompileState;
+import com.sun.tools.javac.comp.Modules;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
@@ -66,9 +71,12 @@
 
     private final JavaCompiler javaCompiler;
     private final Symtab syms;
+    private final Modules modules;
     private final Names names;
     private final Types types;
     private final Enter enter;
+    private final JavacTaskImpl javacTaskImpl;
+    private final CompileStates compileStates;
 
     public static JavacElements instance(Context context) {
         JavacElements instance = context.get(JavacElements.class);
@@ -81,43 +89,66 @@
         context.put(JavacElements.class, this);
         javaCompiler = JavaCompiler.instance(context);
         syms = Symtab.instance(context);
+        modules = Modules.instance(context);
         names = Names.instance(context);
         types = Types.instance(context);
         enter = Enter.instance(context);
+        JavacTask t = context.get(JavacTask.class);
+        javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null;
+        compileStates = CompileStates.instance(context);
+    }
+
+    @Override @DefinedBy(Api.LANGUAGE_MODEL)
+    public ModuleSymbol getModuleElement(CharSequence name) {
+        ensureEntered("getModuleElement");
+        String strName = name.toString();
+        if (strName.equals(""))
+            return syms.unnamedModule;
+        return modules.getObservableModule(names.fromString(strName));
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
     public PackageSymbol getPackageElement(CharSequence name) {
+        ensureEntered("getPackageElement");
+        return getPackageElement(modules.getDefaultModule(), name);
+    }
+
+    public PackageSymbol getPackageElement(ModuleElement module, CharSequence name) {
         String strName = name.toString();
         if (strName.equals(""))
-            return syms.unnamedPackage;
+            return syms.unnamedModule.unnamedPackage;
         return SourceVersion.isName(strName)
-            ? nameToSymbol(strName, PackageSymbol.class)
+            ? nameToSymbol((ModuleSymbol) module, strName, PackageSymbol.class)
             : null;
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
     public ClassSymbol getTypeElement(CharSequence name) {
+        ensureEntered("getTypeElement");
+        return getTypeElement(modules.getDefaultModule(), name);
+    }
+
+    public ClassSymbol getTypeElement(ModuleElement module, CharSequence name) {
         String strName = name.toString();
         return SourceVersion.isName(strName)
-            ? nameToSymbol(strName, ClassSymbol.class)
+            ? nameToSymbol((ModuleSymbol) module, strName, ClassSymbol.class)
             : null;
     }
 
     /**
-     * Returns a symbol given the type's or packages's canonical name,
+     * Returns a symbol given the type's or package's canonical name,
      * or null if the name isn't found.
      */
-    private <S extends Symbol> S nameToSymbol(String nameStr, Class<S> clazz) {
+    private <S extends Symbol> S nameToSymbol(ModuleSymbol module, String nameStr, Class<S> clazz) {
         Name name = names.fromString(nameStr);
         // First check cache.
         Symbol sym = (clazz == ClassSymbol.class)
-                    ? syms.classes.get(name)
-                    : syms.packages.get(name);
+                    ? syms.getClass(module, name)
+                    : syms.lookupPackage(module, name);
 
         try {
             if (sym == null)
-                sym = javaCompiler.resolveIdent(nameStr);
+                sym = javaCompiler.resolveIdent(module, nameStr);
 
             sym.complete();
 
@@ -334,6 +365,12 @@
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
+    public ModuleElement getModuleOf(Element e) {
+        Symbol sym = cast(Symbol.class, e);
+        return (sym.kind == MDL) ? ((ModuleElement) e) : sym.packge().modle;
+    }
+
+    @DefinedBy(Api.LANGUAGE_MODEL)
     public boolean isDeprecated(Element e) {
         Symbol sym = cast(Symbol.class, e);
         return (sym.flags() & Flags.DEPRECATED) != 0;
@@ -601,6 +638,15 @@
                 : null;
     }
 
+    private void ensureEntered(String methodName) {
+        if (javacTaskImpl != null) {
+            javacTaskImpl.ensureEntered();
+        }
+        if (!javaCompiler.isEnterDone()) {
+            throw new IllegalStateException("Cannot use Elements." + methodName + " before the TaskEvent.Kind.ENTER finished event.");
+        }
+    }
+
     /**
      * Returns an object cast to the specified type.
      * @throws NullPointerException if the object is {@code null}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 9af4c19..c0b69a9 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -34,6 +34,7 @@
 import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
 import com.sun.tools.javac.resources.CompilerProperties;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
@@ -158,6 +159,7 @@
         this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
         this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
         this.allowTypeAnnotations = source.allowTypeAnnotations();
+        this.allowModules = source.allowModules();
         this.allowAnnotationsAfterTypeParams = source.allowAnnotationsAfterTypeParams();
         this.allowUnderscoreIdentifier = source.allowUnderscoreIdentifier();
         this.allowPrivateInterfaceMethods = source.allowPrivateInterfaceMethods();
@@ -206,6 +208,10 @@
      */
     boolean allowMethodReferences;
 
+    /** Switch: should we recognize modules?
+     */
+    boolean allowModules;
+
     /** Switch: should we allow default methods in interfaces?
      */
     boolean allowDefaultMethods;
@@ -3096,59 +3102,65 @@
         Token firstToken = token;
         JCModifiers mods = null;
         boolean consumedToplevelDoc = false;
-        boolean seenImport = false;
-        boolean seenPackage = false;
         ListBuffer<JCTree> defs = new ListBuffer<>();
-        if (token.kind == MONKEYS_AT)
-            mods = modifiersOpt();
 
-        if (token.kind == PACKAGE) {
-            int packagePos = token.pos;
-            List<JCAnnotation> annotations = List.nil();
-            seenPackage = true;
-            if (mods != null) {
-                checkNoMods(mods.flags);
-                annotations = mods.annotations;
-                mods = null;
-            }
-            nextToken();
-            JCExpression pid = qualident(false);
-            accept(SEMI);
-            JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
-            attach(pd, firstToken.comment(CommentStyle.JAVADOC));
+        if (token.kind == IDENTIFIER && token.name() == names.module) {
+            defs.append(moduleDecl(token.comment(CommentStyle.JAVADOC)));
             consumedToplevelDoc = true;
-            storeEnd(pd, token.pos);
-            defs.append(pd);
+        } else {
+            boolean seenImport = false;
+            boolean seenPackage = false;
+            if (token.kind == MONKEYS_AT)
+                mods = modifiersOpt();
+
+            if (token.kind == PACKAGE) {
+                int packagePos = token.pos;
+                List<JCAnnotation> annotations = List.nil();
+                seenPackage = true;
+                if (mods != null) {
+                    checkNoMods(mods.flags);
+                    annotations = mods.annotations;
+                    mods = null;
+                }
+                nextToken();
+                JCExpression pid = qualident(false);
+                accept(SEMI);
+                JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
+                attach(pd, firstToken.comment(CommentStyle.JAVADOC));
+                consumedToplevelDoc = true;
+                storeEnd(pd, token.pos);
+                defs.append(pd);
+            }
+            boolean checkForImports = true;
+            boolean firstTypeDecl = true;
+            while (token.kind != EOF) {
+                if (token.pos <= endPosTable.errorEndPos) {
+                    // error recovery
+                    skip(checkForImports, false, false, false);
+                    if (token.kind == EOF)
+                        break;
+                }
+                if (checkForImports && mods == null && token.kind == IMPORT) {
+                    seenImport = true;
+                    defs.append(importDeclaration());
+                } else {
+                    Comment docComment = token.comment(CommentStyle.JAVADOC);
+                    if (firstTypeDecl && !seenImport && !seenPackage) {
+                        docComment = firstToken.comment(CommentStyle.JAVADOC);
+                        consumedToplevelDoc = true;
+                    }
+                    JCTree def = typeDeclaration(mods, docComment);
+                    if (def instanceof JCExpressionStatement)
+                        def = ((JCExpressionStatement)def).expr;
+                    defs.append(def);
+                    if (def instanceof JCClassDecl)
+                        checkForImports = false;
+                    mods = null;
+                    firstTypeDecl = false;
+                }
+            }
         }
 
-        boolean checkForImports = true;
-        boolean firstTypeDecl = true;
-        while (token.kind != EOF) {
-            if (token.pos <= endPosTable.errorEndPos) {
-                // error recovery
-                skip(checkForImports, false, false, false);
-                if (token.kind == EOF)
-                    break;
-            }
-            if (checkForImports && mods == null && token.kind == IMPORT) {
-                seenImport = true;
-                defs.append(importDeclaration());
-            } else {
-                Comment docComment = token.comment(CommentStyle.JAVADOC);
-                if (firstTypeDecl && !seenImport && !seenPackage) {
-                    docComment = firstToken.comment(CommentStyle.JAVADOC);
-                    consumedToplevelDoc = true;
-                }
-                JCTree def = typeDeclaration(mods, docComment);
-                if (def instanceof JCExpressionStatement)
-                    def = ((JCExpressionStatement)def).expr;
-                defs.append(def);
-                if (def instanceof JCClassDecl)
-                    checkForImports = false;
-                mods = null;
-                firstTypeDecl = false;
-            }
-        }
         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList());
         if (!consumedToplevelDoc)
             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
@@ -3163,6 +3175,75 @@
         return toplevel;
     }
 
+    JCModuleDecl moduleDecl(Comment dc) {
+        int pos = token.pos;
+        if (!allowModules) {
+            log.error(pos, Errors.ModulesNotSupportedInSource(source.name));
+            allowModules = true;
+        }
+
+        nextToken();
+        JCExpression name = qualident(false);
+        List<JCDirective> directives = null;
+
+        accept(LBRACE);
+        directives = moduleDirectiveList();
+        accept(RBRACE);
+        accept(EOF);
+
+        JCModuleDecl result = toP(F.at(pos).ModuleDef(name, directives));
+        attach(result, dc);
+        return result;
+    }
+
+    List<JCDirective> moduleDirectiveList() {
+        ListBuffer<JCDirective> defs = new ListBuffer<>();
+        while (token.kind == IDENTIFIER) {
+            int pos = token.pos;
+            if (token.name() == names.requires) {
+                nextToken();
+                boolean isPublic = false;
+                if (token.kind == PUBLIC) {
+                    isPublic = true;
+                    nextToken();
+                }
+                JCExpression moduleName = qualident(false);
+                accept(SEMI);
+                defs.append(toP(F.at(pos).Requires(isPublic, moduleName)));
+            } else if (token.name() == names.exports) {
+                nextToken();
+                JCExpression pkgName = qualident(false);
+                List<JCExpression> moduleNames = null;
+                if (token.kind == IDENTIFIER && token.name() == names.to) {
+                    nextToken();
+                    moduleNames = qualidentList();
+                }
+                accept(SEMI);
+                defs.append(toP(F.at(pos).Exports(pkgName, moduleNames)));
+            } else if (token.name() == names.provides) {
+                nextToken();
+                JCExpression serviceName = qualident(false);
+                if (token.kind == IDENTIFIER && token.name() == names.with) {
+                    nextToken();
+                    JCExpression implName = qualident(false);
+                    accept(SEMI);
+                    defs.append(toP(F.at(pos).Provides(serviceName, implName)));
+                } else {
+                    error(token.pos, "expected", "'" + names.with + "'");
+                    skip(false, false, false, false);
+                }
+            } else if (token.name() == names.uses) {
+                nextToken();
+                JCExpression service = qualident(false);
+                accept(SEMI);
+                defs.append(toP(F.at(pos).Uses(service)));
+            } else {
+                break;
+            }
+        }
+        return defs.toList();
+    }
+
     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
      */
     protected JCTree importDeclaration() {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
index 9165f9b..30da707 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
@@ -27,8 +27,10 @@
 
 import java.io.Closeable;
 import java.io.File;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.file.Path;
@@ -42,6 +44,7 @@
 import javax.lang.model.util.*;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
 import javax.tools.StandardJavaFileManager;
 
 import static javax.tools.StandardLocation.*;
@@ -49,6 +52,7 @@
 import com.sun.source.util.TaskEvent;
 import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.ClassType;
 import com.sun.tools.javac.code.Types;
@@ -56,12 +60,14 @@
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.model.JavacElements;
 import com.sun.tools.javac.model.JavacTypes;
 import com.sun.tools.javac.platform.PlatformDescription;
 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.Abort;
@@ -77,10 +83,10 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.MatchingUtils;
+import com.sun.tools.javac.util.ModuleHelper;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.javac.util.Options;
-import com.sun.tools.javac.util.ServiceLoader;
 
 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -112,8 +118,10 @@
     private final JavacMessager messager;
     private final JavacElements elementUtils;
     private final JavacTypes typeUtils;
-    private final Types types;
     private final JavaCompiler compiler;
+    private final Modules modules;
+    private final ModuleHelper moduleHelper;
+    private final Types types;
 
     /**
      * Holds relevant state history of which processors have been
@@ -154,7 +162,10 @@
     Source source;
 
     private ClassLoader processorClassLoader;
-    private SecurityException processorClassLoaderException;
+    private ServiceLoader<Processor> serviceLoader;
+    private SecurityException processorLoaderException;
+
+    private final JavaFileManager fileManager;
 
     /**
      * JavacMessages object used for localization
@@ -167,6 +178,7 @@
     private final Enter enter;
     private final Completer initialCompleter;
     private final Check chk;
+    private final ModuleSymbol defaultModule;
 
     private final Context context;
 
@@ -196,6 +208,7 @@
         fatalErrors = options.isSet("fatalEnterError");
         showResolveErrors = options.isSet("showResolveErrors");
         werror = options.isSet(WERROR);
+        fileManager = context.get(JavaFileManager.class);
         platformAnnotations = initPlatformAnnotations();
 
         // Initialize services before any processors are initialized
@@ -204,6 +217,7 @@
         messager = new JavacMessager(context, this);
         elementUtils = JavacElements.instance(context);
         typeUtils = JavacTypes.instance(context);
+        modules = Modules.instance(context);
         types = Types.instance(context);
         processorOptions = initProcessorOptions();
         unmatchedProcessorOptions = initUnmatchedProcessorOptions();
@@ -214,7 +228,11 @@
         enter = Enter.instance(context);
         initialCompleter = ClassFinder.instance(context).getCompleter();
         chk = Check.instance(context);
-        initProcessorClassLoader();
+        moduleHelper = ModuleHelper.instance(context);
+        initProcessorLoader();
+
+        defaultModule = source.allowModules() && options.isUnset("noModules")
+                ? symtab.unnamedModule : symtab.noModule;
     }
 
     public void setProcessors(Iterable<? extends Processor> processors) {
@@ -234,19 +252,28 @@
         return Collections.unmodifiableSet(platformAnnotations);
     }
 
-    private void initProcessorClassLoader() {
-        JavaFileManager fileManager = context.get(JavaFileManager.class);
+    private void initProcessorLoader() {
         try {
-            // If processorpath is not explicitly set, use the classpath.
-            processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
-                ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
-                : fileManager.getClassLoader(CLASS_PATH);
+            if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+                try {
+                    serviceLoader = fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, Processor.class);
+                } catch (IOException e) {
+                    throw new Abort(e);
+                }
+            } else {
+                // If processorpath is not explicitly set, use the classpath.
+                processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
+                    ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
+                    : fileManager.getClassLoader(CLASS_PATH);
 
-            if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
-                compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
+                moduleHelper.addExports(processorClassLoader);
+
+                if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
+                    compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
+                }
             }
         } catch (SecurityException e) {
-            processorClassLoaderException = e;
+            processorLoaderException = e;
         }
     }
 
@@ -266,14 +293,18 @@
         } else if (processors != null) {
             processorIterator = processors.iterator();
         } else {
-            String processorNames = options.get(PROCESSOR);
-            if (processorClassLoaderException == null) {
+            if (processorLoaderException == null) {
                 /*
                  * If the "-processor" option is used, search the appropriate
                  * path for the named class.  Otherwise, use a service
                  * provider mechanism to create the processor iterator.
                  */
-                if (processorNames != null) {
+                String processorNames = options.get(PROCESSOR);
+                if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+                    processorIterator = (processorNames == null) ?
+                            new ServiceIterator(serviceLoader, log) :
+                            new NameServiceIterator(serviceLoader, log, processorNames);
+                } else if (processorNames != null) {
                     processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
                 } else {
                     processorIterator = new ServiceIterator(processorClassLoader, log);
@@ -286,7 +317,7 @@
                  * in service configuration file.) Otherwise, we cannot continue.
                  */
                 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
-                        processorClassLoaderException);
+                        processorLoaderException);
             }
         }
         PlatformDescription platformProvider = context.get(PlatformDescription.class);
@@ -304,6 +335,18 @@
         discoveredProcs = new DiscoveredProcessors(compoundIterator);
     }
 
+    public <S> ServiceLoader<S> getServiceLoader(Class<S> service) {
+        if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+            try {
+                return fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, service);
+            } catch (IOException e) {
+                throw new Abort(e);
+            }
+        } else {
+            return ServiceLoader.load(service, getProcessorClassLoader());
+        }
+    }
+
     /**
      * Returns an empty processor iterator if no processors are on the
      * relevant path, otherwise if processors are present, logs an
@@ -316,8 +359,6 @@
      * @param e   If non-null, pass this exception to Abort
      */
     private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
-        JavaFileManager fileManager = context.get(JavaFileManager.class);
-
         if (fileManager instanceof JavacFileManager) {
             StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
             Iterable<? extends Path> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
@@ -355,9 +396,9 @@
      * needed but unavailable.
      */
     private class ServiceIterator implements Iterator<Processor> {
-        private Iterator<Processor> iterator;
-        private Log log;
-        private ServiceLoader<Processor> loader;
+        Iterator<Processor> iterator;
+        Log log;
+        ServiceLoader<Processor> loader;
 
         ServiceIterator(ClassLoader classLoader, Log log) {
             this.log = log;
@@ -375,9 +416,16 @@
             }
         }
 
+        ServiceIterator(ServiceLoader<Processor> loader, Log log) {
+            this.log = log;
+            this.loader = loader;
+            this.iterator = loader.iterator();
+        }
+
+        @Override
         public boolean hasNext() {
             try {
-                return iterator.hasNext();
+                return internalHasNext();
             } catch(ServiceConfigurationError sce) {
                 log.error("proc.bad.config.file", sce.getLocalizedMessage());
                 throw new Abort(sce);
@@ -386,9 +434,14 @@
             }
         }
 
+        boolean internalHasNext() {
+            return iterator.hasNext();
+        }
+
+        @Override
         public Processor next() {
             try {
-                return iterator.next();
+                return internalNext();
             } catch (ServiceConfigurationError sce) {
                 log.error("proc.bad.config.file", sce.getLocalizedMessage());
                 throw new Abort(sce);
@@ -397,6 +450,11 @@
             }
         }
 
+        Processor internalNext() {
+            return iterator.next();
+        }
+
+        @Override
         public void remove() {
             throw new UnsupportedOperationException();
         }
@@ -412,6 +470,58 @@
         }
     }
 
+    private class NameServiceIterator extends ServiceIterator {
+        private Map<String, Processor> namedProcessorsMap = new HashMap<>();;
+        private Iterator<String> processorNames = null;
+        private Processor nextProc = null;
+
+        public NameServiceIterator(ServiceLoader<Processor> loader, Log log, String theNames) {
+            super(loader, log);
+            this.processorNames = Arrays.asList(theNames.split(",")).iterator();
+        }
+
+        @Override
+        boolean internalHasNext() {
+            if (nextProc != null) {
+                return true;
+            }
+            if (!processorNames.hasNext()) {
+                namedProcessorsMap = null;
+                return false;
+            }
+            String processorName = processorNames.next();
+            Processor theProcessor = namedProcessorsMap.get(processorName);
+            if (theProcessor != null) {
+                namedProcessorsMap.remove(processorName);
+                nextProc = theProcessor;
+                return true;
+            } else {
+                while (iterator.hasNext()) {
+                    theProcessor = iterator.next();
+                    String name = theProcessor.getClass().getName();
+                    if (name.equals(processorName)) {
+                        nextProc = theProcessor;
+                        return true;
+                    } else {
+                        namedProcessorsMap.put(name, theProcessor);
+                    }
+                }
+                log.error(Errors.ProcProcessorNotFound(processorName));
+                return false;
+            }
+        }
+
+        @Override
+        Processor internalNext() {
+            if (hasNext()) {
+                Processor p = nextProc;
+                nextProc = null;
+                return p;
+            } else {
+                throw new NoSuchElementException();
+            }
+        }
+    }
 
     private static class NameProcessIterator implements Iterator<Processor> {
         Processor nextProc = null;
@@ -437,8 +547,10 @@
                     Processor processor;
                     try {
                         try {
+                            Class<?> processorClass = processorCL.loadClass(processorName);
+                            ensureReadable(processorClass);
                             processor =
-                                (Processor) (processorCL.loadClass(processorName).newInstance());
+                                (Processor) (processorClass.newInstance());
                         } catch (ClassNotFoundException cnfe) {
                             log.error("proc.processor.not.found", processorName);
                             return false;
@@ -473,6 +585,26 @@
         public void remove () {
             throw new UnsupportedOperationException();
         }
+
+        /**
+         * Ensures that the module of the given class is readable to this
+         * module.
+         */
+        private void ensureReadable(Class<?> targetClass) {
+            try {
+                Method getModuleMethod = Class.class.getMethod("getModule");
+                Object thisModule = getModuleMethod.invoke(this.getClass());
+                Object targetModule = getModuleMethod.invoke(targetClass);
+
+                Class<?> moduleClass = getModuleMethod.getReturnType();
+                Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+                addReadsMethod.invoke(thisModule, targetModule);
+            } catch (NoSuchMethodException e) {
+                // ignore
+            } catch (Exception e) {
+                throw new InternalError(e);
+            }
+        }
     }
 
     public boolean atLeastOneProcessor() {
@@ -605,7 +737,7 @@
     // TODO: These two classes can probably be rewritten better...
     /**
      * This class holds information about the processors that have
-     * been discoverd so far as well as the means to discover more, if
+     * been discovered so far as well as the means to discover more, if
      * necessary.  A single iterator should be used per round of
      * annotation processing.  The iterator first visits already
      * discovered processors then fails over to the service provider
@@ -1000,21 +1132,24 @@
                 if (file.getKind() != JavaFileObject.Kind.CLASS)
                     throw new AssertionError(file);
                 ClassSymbol cs;
+                // TODO: for now, we assume that generated code is in a default module;
+                // in time, we need a way to be able to specify the module for generated code
                 if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
                     Name packageName = Convert.packagePart(name);
-                    PackageSymbol p = symtab.enterPackage(packageName);
+                    PackageSymbol p = symtab.enterPackage(defaultModule, packageName);
                     if (p.package_info == null)
-                        p.package_info = symtab.enterClass(Convert.shortName(name), p);
+                        p.package_info = symtab.enterClass(defaultModule, Convert.shortName(name), p);
                     cs = p.package_info;
                     cs.reset();
                     if (cs.classfile == null)
                         cs.classfile = file;
                     cs.completer = initialCompleter;
                 } else {
-                    cs = symtab.enterClass(name);
+                    cs = symtab.enterClass(defaultModule, name);
                     cs.reset();
                     cs.classfile = file;
                     cs.completer = initialCompleter;
+                    cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
                 }
                 list = list.prepend(cs);
             }
@@ -1023,7 +1158,7 @@
 
         /** Enter a set of syntax trees. */
         private void enterTrees(List<JCCompilationUnit> roots) {
-            compiler.enterTrees(roots);
+            compiler.enterTrees(compiler.initModules(roots));
         }
 
         /** Run a processing round. */
@@ -1099,11 +1234,12 @@
             filer.newRound();
             messager.newRound();
             compiler.newRound();
+            modules.newRound();
             types.newRound();
 
             boolean foundError = false;
 
-            for (ClassSymbol cs : symtab.classes.values()) {
+            for (ClassSymbol cs : symtab.getAllClasses()) {
                 if (cs.kind == ERR) {
                     foundError = true;
                     break;
@@ -1111,7 +1247,7 @@
             }
 
             if (foundError) {
-                for (ClassSymbol cs : symtab.classes.values()) {
+                for (ClassSymbol cs : symtab.getAllClasses()) {
                     if (cs.classfile != null || cs.kind == ERR) {
                         cs.reset();
                         cs.type = new ClassType(cs.type.getEnclosingType(), null, cs);
@@ -1350,6 +1486,13 @@
                     }
                     node.packge.reset();
                 }
+                boolean isModuleInfo = node.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
+                if (isModuleInfo) {
+                    node.modle.reset();
+                    node.modle.completer = sym -> modules.enter(List.of(node), node.modle.module_info);
+                    node.modle.module_info.reset();
+                    node.modle.module_info.members_field = WriteableScope.create(node.modle.module_info);
+                }
                 node.packge = null;
                 topLevel = node;
                 try {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index 2194546..db73116 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -1,4 +1,3 @@
-
 #
 # Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -814,6 +813,10 @@
     {0} is not an annotation type
 
 # 0: symbol, 1: symbol
+compiler.err.not.def.access.package.cant.access=\
+    {0} is not visible because package {1} is not visible
+
+# 0: symbol, 1: symbol
 compiler.err.not.def.access.class.intf.cant.access=\
     {0} in {1} is defined in an inaccessible class or interface
 
@@ -1176,6 +1179,43 @@
 compiler.err.plugin.not.found=\
     plug-in not found: {0}
 
+# 0: path
+compiler.warn.locn.unknown.file.on.module.path=\
+    unknown file on module path: {0}
+
+
+# 0: path
+compiler.err.locn.bad.module-info=\
+    problem reading module-info.class in {0}
+
+# 0: path
+compiler.err.locn.cant.read.directory=\
+    cannot read directory {0}
+
+# 0: path
+compiler.err.locn.cant.read.file=\
+    cannot read file {0}
+
+# 0: path
+compiler.err.locn.cant.get.module.name.for.jar=\
+    cannot determine module name for {0}
+
+# 0: path
+compiler.err.multi-module.outdir.cannot.be.exploded.module=\
+    in multi-module mode, the output directory cannot be an exploded module: {0}
+
+# 0: path
+compiler.warn.outdir.is.in.exploded.module=\
+    the output directory is within an exploded module: {0}
+
+# 0: path
+compiler.err.locn.module-info.not.allowed.on.patch.path=\
+    module-info.class not allowed on patch path: {0}
+
+# 0: string
+compiler.err.locn.invalid.arg.for.xpatch=\
+    invalid argument for -Xpatch option: {0}
+
 #####
 
 # Fatal Errors
@@ -1379,6 +1419,10 @@
 compiler.warn.dir.path.element.not.found=\
     bad path element "{0}": no such directory
 
+# 0: file name
+compiler.warn.dir.path.element.not.directory=\
+    bad path element "{0}": not a directory
+
 compiler.warn.finally.cannot.complete=\
     finally clause cannot complete normally
 
@@ -1492,7 +1536,7 @@
     {0} attribute introduced in version {1}.{2} class files is ignored in version {3}.{4} class files
 
 # Warnings related to annotation processing
-# 0: name
+# 0: string
 compiler.warn.proc.package.does.not.exist=\
     package {0} does not exist
 
@@ -1733,6 +1777,9 @@
 compiler.misc.unnamed.package=\
     unnamed package
 
+compiler.misc.unnamed.module=\
+    unnamed module
+
 #####
 
 # 0: symbol, 1: message segment
@@ -1789,6 +1836,9 @@
 compiler.misc.bad.type.annotation.value=\
     bad type annotation target type value: {0}
 
+compiler.misc.bad.module-info.name=\
+    bad class name
+
 compiler.misc.class.file.wrong.class=\
     class file contains wrong class: {0}
 
@@ -1810,6 +1860,9 @@
 compiler.misc.file.does.not.contain.package=\
     file does not contain package {0}
 
+compiler.misc.file.does.not.contain.module=\
+    file does not contain module declaration
+
 compiler.misc.illegal.start.of.class.file=\
     illegal start of class file
 
@@ -2176,6 +2229,9 @@
 compiler.misc.kindname.package=\
     package
 
+compiler.misc.kindname.module=\
+    module
+
 compiler.misc.kindname.static.init=\
     static initializer
 
@@ -2278,6 +2334,12 @@
 ########################################
 # Diagnostics for language feature changes
 ########################################
+
+# 0: string
+compiler.err.modules.not.supported.in.source=\
+   modules are not supported in -source {0}\n\
+    (use -source 9 or higher to enable modules)
+
 # 0: string
 compiler.misc.diamond.and.anon.class.not.supported.in.source=\
     cannot use ''<>'' with anonymous inner classes in -source {0}\n\
@@ -2608,4 +2670,170 @@
 compiler.err.dc.unterminated.string=\
     unterminated string
 
+###
+# errors related to modules
 
+compiler.err.expected.module=\
+    expected ''module''
+
+# 0: symbol
+compiler.err.module.not.found=\
+    module not found: {0}
+
+compiler.err.too.many.modules=\
+    too many module declarations found
+
+# 0: symbol
+compiler.err.duplicate.module=\
+    duplicate module: {0}
+
+# 0: symbol
+compiler.err.duplicate.requires=\
+    duplicate requires: {0}
+
+# 0: symbol
+compiler.err.duplicate.exports=\
+    duplicate export: {0}
+
+# 0: symbol, 1: symbol
+compiler.err.duplicate.provides=\
+    duplicate provides: service {0}, implementation {1}
+
+# 0: symbol
+compiler.err.duplicate.uses=\
+    duplicate uses: {0}
+
+# 0: symbol
+compiler.err.service.implementation.is.abstract=\
+    the service implementation is an abstract class: {0}
+
+# 0: symbol
+compiler.err.service.implementation.is.inner=\
+    the service implementation is an inner class: {0}
+
+# 0: symbol
+compiler.err.service.definition.is.inner=\
+    the service definition is an inner class: {0}
+
+# 0: symbol
+compiler.err.service.implementation.doesnt.have.a.no.args.constructor=\
+    the service implementation does not have a default constructor: {0}
+
+# 0: symbol
+compiler.err.service.implementation.no.args.constructor.not.public=\
+    the no arguments constructor of the service implementation is not public: {0}
+
+# 0: symbol
+compiler.err.package.empty.or.not.found=\
+    package is empty or does not exist: {0}
+
+compiler.err.no.output.dir=\
+    no class output directory specified
+
+compiler.err.unnamed.pkg.not.allowed.named.modules=\
+    unnamed package is not allowed in named modules
+
+# 0: name, 1: name
+compiler.err.module.name.mismatch=\
+    module name {0} does not match expected name {1}
+
+compiler.err.module.decl.sb.in.module-info.java=\
+    module declarations should be in a file named module-info.java
+
+compiler.err.unexpected.after.module=\
+    unexpected input after module declaration
+
+compiler.err.module-info.with.xmodule.sourcepath=\
+    illegal combination of -Xmodule and module-info on sourcepath
+
+compiler.err.module-info.with.xmodule.classpath=\
+    illegal combination of -Xmodule and module-info on classpath
+
+compiler.err.xmodule.no.module.sourcepath=\
+    illegal combination of -Xmodule and -modulesourcepath
+
+compiler.err.processorpath.no.processormodulepath=\
+    illegal combination of -processorpath and -processormodulepath
+
+# 0: symbol
+compiler.err.package.in.other.module=\
+    package exists in another module: {0}
+
+# 0: symbol, 1: name, 2: symbol, 3: symbol
+compiler.err.package.clash.from.requires=\
+    module {0} reads package {1} from both {2} and {3}
+
+# 0: string
+compiler.err.module.not.found.in.module.source.path=\
+    module {0} not found in module source path
+
+compiler.err.output.dir.must.be.specified.with.dash.m.option=\
+    class output directory must be specified if -m option is used
+
+compiler.err.modulesourcepath.must.be.specified.with.dash.m.option=\
+    module source path must be specified if -m option is used
+
+# 0: symbol
+compiler.err.service.implementation.not.in.right.module=\
+    service implementation must be defined in the same module as the provides directive
+
+# 0: symbol
+compiler.err.cyclic.requires=\
+    cyclic dependence involving {0}
+
+# 0: fragment, 1: name
+compiler.err.duplicate.module.on.path=\
+    duplicate module on {0}\nmodule in {1}
+
+# 0:  string
+compiler.err.xaddexports.malformed.entry=\
+    bad value for -XaddExports: {0}
+
+# 0: string
+compiler.err.xaddexports.too.many=\
+    multiple -XaddExports options for {0}
+
+# 0:  string
+compiler.err.xaddreads.malformed.entry=\
+    bad value for -XaddReads: {0}
+
+# 0: string
+compiler.err.xaddreads.too.many=\
+    multiple -XaddReads options for {0}
+
+compiler.err.addmods.all.module.path.invalid=\
+    -addmods ALL-MODULE-PATH can only be used when compiling the unnamed module
+
+compiler.misc.locn.module_source_path=\
+    module source path
+
+compiler.misc.locn.upgrade_module_path=\
+    upgrade module path
+
+compiler.misc.locn.system_modules=\
+    system modules
+
+compiler.misc.locn.module_path=\
+    application module path
+
+compiler.misc.cant.resolve.modules=\
+    cannot resolve modules
+
+# 0: symbol
+compiler.err.cant.find.module=\
+    cannot find module: {0}
+
+# 0: string
+compiler.err.invalid.module.specifier=\
+    module specifier not allowed: {0}
+
+# 0: symbol
+compiler.warn.service.provided.but.not.exported.or.used=\
+    service interface provided but not exported or used
+
+###
+# errors related to options
+
+# 0: string, 1: string
+compiler.err.illegal.argument.for.option=\
+    illegal argument for {0}: {1}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
index 7246acf..3df72ad 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
@@ -39,20 +39,34 @@
     Output source locations where deprecated APIs are used
 javac.opt.classpath=\
     Specify where to find user class files and annotation processors
+javac.opt.modulepath=\
+    Specify where to find application modules
 javac.opt.sourcepath=\
     Specify where to find input source files
+javac.opt.m=\
+    Compile only the specified module, check timestamps
+javac.opt.modulesourcepath=\
+    Specify where to find input source files for multiple modules
 javac.opt.bootclasspath=\
     Override location of bootstrap class files
+javac.opt.system=\
+    Override location of system modules
+javac.opt.upgrademodulepath=\
+    Override location of upgradeable modules
 javac.opt.Xbootclasspath.p=\
     Prepend to the bootstrap class path
 javac.opt.Xbootclasspath.a=\
     Append to the bootstrap class path
+javac.opt.Xpatch=\
+    Specify location of module class files to patch
 javac.opt.endorseddirs=\
     Override location of endorsed standards path
 javac.opt.extdirs=\
     Override location of installed extensions
 javac.opt.processorpath=\
     Specify where to find annotation processors
+javac.opt.processormodulepath=\
+    Specify a module path where to find annotation processors
 javac.opt.processor=\
     Names of the annotation processors to run; bypasses default discovery process
 javac.opt.parameters=\
@@ -95,6 +109,12 @@
     key[=value]
 javac.opt.arg.path=\
     <path>
+javac.opt.arg.mspath=\
+    <module-source-path>
+javac.opt.arg.m=\
+    <module-name>
+javac.opt.arg.jdk=\
+    <jdk>|none
 javac.opt.arg.dirs=\
     <dirs>
 javac.opt.arg.directory=\
@@ -252,6 +272,29 @@
     Read options and filenames from file
 javac.opt.diags=\
     Select a diagnostic mode
+javac.opt.addExports=\n\
+\        Specify a package to be considered as exported from its defining module\n\
+\        to additional modules, or to all unnamed modules if <other-module> is ALL-UNNAMED.
+javac.opt.arg.addExports=\
+    <module>/<package>=<other-module>(,<other-module>)*
+javac.opt.addReads=\n\
+\        Specify additional modules to be considered as required by a given module.\n\
+\        <other-module> may be ALL-UNNAMED to require the unnamed module.
+javac.opt.arg.addReads=\
+    <module>=<other-module>(,<other-module>)*
+javac.opt.module=\
+    Specify a module to which the classes being compiled belong.
+javac.opt.arg.module=\
+    <module-name>
+javac.opt.addmods=\n\
+\        Root modules to resolve in addition to the initial modules, or all modules\n\
+\        on the module path if <module> is ALL-MODULE-PATH.
+javac.opt.arg.addmods=\
+    <module>(,<module>)*
+javac.opt.limitmods=\
+    Limit the universe of observable modules
+javac.opt.arg.limitmods=\
+    <module>(,<module>)*
 
 ## errors
 
@@ -269,6 +312,10 @@
     invalid profile: {0}
 javac.err.invalid.target=\
     invalid target release: {0}
+javac.err.option.not.allowed.with.target=\
+    option {0} not allowed with target {1}
+javac.err.option.too.many=\
+    option {0} can only be specified once
 javac.err.no.source.files=\
     no source files
 javac.err.no.source.files.classes=\
@@ -279,6 +326,8 @@
     invalid source release: {0}
 javac.err.error.writing.file=\
     error writing {0}; {1}
+javac.err.sourcepath.modulesourcepath.conflict=\
+    cannot specify both -sourcepath and -modulesourcepath
 javac.warn.source.target.conflict=\
     source release {0} requires target release {1}
 javac.warn.target.default.source.conflict=\
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/CreateSymbols.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/CreateSymbols.java
deleted file mode 100644
index acfb5bd..0000000
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/CreateSymbols.java
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.sym;
-
-import com.sun.tools.javac.api.JavacTaskImpl;
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.jvm.ClassWriter;
-import com.sun.tools.javac.jvm.Pool;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Names;
-import com.sun.tools.javac.util.Pair;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.Set;
-
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.annotation.processing.SupportedOptions;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import static javax.tools.JavaFileObject.Kind.CLASS;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/**
- * Used to generate a "symbol file" representing rt.jar that only
- * includes supported or legacy proprietary API.  Valid annotation
- * processor options:
- *
- * <dl>
- * <dt>com.sun.tools.javac.sym.Jar</dt>
- * <dd>Specifies the location of rt.jar.</dd>
- * <dt>com.sun.tools.javac.sym.Dest</dt>
- * <dd>Specifies the destination directory.</dd>
- * </dl>
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own
- * risk.  This code and its internal interfaces are subject to change
- * or deletion without notice.</b></p>
- *
- * @author Peter von der Ah\u00e9
- */
-@SupportedOptions({
-    "com.sun.tools.javac.sym.Jar",
-    "com.sun.tools.javac.sym.Dest",
-    "com.sun.tools.javac.sym.Profiles"})
-@SupportedAnnotationTypes("*")
-public class CreateSymbols extends AbstractProcessor {
-
-    static Set<String> getLegacyPackages() {
-        ResourceBundle legacyBundle
-            = ResourceBundle.getBundle("com.sun.tools.javac.resources.legacy");
-        Set<String> keys = new HashSet<>();
-        for (Enumeration<String> e = legacyBundle.getKeys(); e.hasMoreElements(); )
-            keys.add(e.nextElement());
-        return keys;
-    }
-
-    @DefinedBy(Api.ANNOTATION_PROCESSING)
-    public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
-        try {
-            if (renv.processingOver())
-                createSymbols();
-        } catch (IOException e) {
-            CharSequence msg = e.getLocalizedMessage();
-            if (msg == null)
-                msg = e.toString();
-            processingEnv.getMessager()
-                .printMessage(Diagnostic.Kind.ERROR, msg);
-        } catch (Throwable t) {
-            t.printStackTrace();
-            Throwable cause = t.getCause();
-            if (cause == null)
-                cause = t;
-            CharSequence msg = cause.getLocalizedMessage();
-            if (msg == null)
-                msg = cause.toString();
-            processingEnv.getMessager()
-                .printMessage(Diagnostic.Kind.ERROR, msg);
-        }
-        return true;
-    }
-
-    void createSymbols() throws IOException {
-        Set<String> legacy = getLegacyPackages();
-        Set<String> legacyProprietary = getLegacyPackages();
-        Set<String> documented = new HashSet<>();
-        Set<PackageSymbol> packages =
-            ((JavacProcessingEnvironment)processingEnv).getSpecifiedPackages();
-        Map<String,String> pOptions = processingEnv.getOptions();
-        String jarName = pOptions.get("com.sun.tools.javac.sym.Jar");
-        if (jarName == null)
-            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Jar=LOCATION_OF_JAR");
-        String destName = pOptions.get("com.sun.tools.javac.sym.Dest");
-        if (destName == null)
-            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Dest=LOCATION_OF_JAR");
-        String profileSpec=pOptions.get("com.sun.tools.javac.sym.Profiles");
-        if (profileSpec == null)
-            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Profiles=PROFILES_SPEC");
-        Profiles profiles = Profiles.read(new File(profileSpec));
-
-        for (PackageSymbol psym : packages) {
-            String name = psym.getQualifiedName().toString();
-            legacyProprietary.remove(name);
-            documented.add(name);
-        }
-
-        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
-        Location jarLocation = StandardLocation.locationFor(jarName);
-        File jarFile = new File(jarName);
-        fm.setLocation(jarLocation, List.of(jarFile));
-        fm.setLocation(StandardLocation.CLASS_PATH, List.<File>nil());
-        fm.setLocation(StandardLocation.SOURCE_PATH, List.<File>nil());
-        {
-            ArrayList<File> bootClassPath = new ArrayList<>();
-            bootClassPath.add(jarFile);
-            for (File path : fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {
-                if (!new File(path.getName()).equals(new File("rt.jar")))
-                    bootClassPath.add(path);
-            }
-            System.err.println("Using boot class path = " + bootClassPath);
-            fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
-        }
-        // System.out.println(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH));
-        File destDir = new File(destName);
-        if (!destDir.exists())
-            if (!destDir.mkdirs())
-                throw new RuntimeException("Could not create " + destDir);
-        fm.setLocation(StandardLocation.CLASS_OUTPUT, List.of(destDir));
-        Set<String> hiddenPackages = new HashSet<>();
-        Set<String> crisp = new HashSet<>();
-        List<String> options = List.of("-XDdev");
-        // options = options.prepend("-doe");
-        // options = options.prepend("-verbose");
-        JavacTaskImpl task = (JavacTaskImpl)
-            tool.getTask(null, fm, null, options, null, null);
-        com.sun.tools.javac.main.JavaCompiler compiler =
-            com.sun.tools.javac.main.JavaCompiler.instance(task.getContext());
-        ClassWriter writer = ClassWriter.instance(task.getContext());
-        Symtab syms = Symtab.instance(task.getContext());
-        Names names = Names.instance(task.getContext());
-        Attribute.Compound proprietaryAnno =
-            new Attribute.Compound(syms.proprietaryType,
-                                   List.<Pair<Symbol.MethodSymbol,Attribute>>nil());
-        Attribute.Compound[] profileAnnos = new Attribute.Compound[profiles.getProfileCount() + 1];
-        Symbol.MethodSymbol profileValue = (MethodSymbol) syms.profileType.tsym.members().findFirst(names.value);
-        for (int i = 1; i < profileAnnos.length; i++) {
-            profileAnnos[i] = new Attribute.Compound(syms.profileType,
-                    List.<Pair<Symbol.MethodSymbol, Attribute>>of(
-                        new Pair<Symbol.MethodSymbol, Attribute>(profileValue,
-                        new Attribute.Constant(syms.intType, i))));
-        }
-
-        Type.moreInfo = true;
-        Types types = Types.instance(task.getContext());
-        Pool pool = new Pool(types);
-        for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
-            String className = fm.inferBinaryName(jarLocation, file);
-            int index = className.lastIndexOf('.');
-            String pckName = index == -1 ? "" : className.substring(0, index);
-            boolean addLegacyAnnotation = false;
-            if (documented.contains(pckName)) {
-                if (!legacy.contains(pckName))
-                    crisp.add(pckName);
-                // System.out.println("Documented: " + className);
-            } else if (legacyProprietary.contains(pckName)) {
-                addLegacyAnnotation = true;
-                // System.out.println("Legacy proprietary: " + className);
-            } else {
-                // System.out.println("Hidden " + className);
-                hiddenPackages.add(pckName);
-                continue;
-            }
-            TypeSymbol sym = (TypeSymbol)compiler.resolveIdent(className);
-            if (sym.kind != TYP) {
-                if (className.indexOf('$') < 0) {
-                    System.err.println("Ignoring (other) " + className + " : " + sym);
-                    System.err.println("   " + sym.getClass().getSimpleName() + " " + sym.type);
-                }
-                continue;
-            }
-            sym.complete();
-            if (sym.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
-                System.err.println("Ignoring (bad) " + sym.getQualifiedName());
-                continue;
-            }
-            ClassSymbol cs = (ClassSymbol) sym;
-            if (addLegacyAnnotation) {
-                cs.prependAttributes(List.of(proprietaryAnno));
-            }
-            int p = profiles.getProfile(cs.fullname.toString().replace(".", "/"));
-            if (0 < p && p < profileAnnos.length)
-                cs.prependAttributes(List.of(profileAnnos[p]));
-            writeClass(pool, cs, writer);
-        }
-
-        if (false) {
-            for (String pckName : crisp)
-                System.out.println("Crisp: " + pckName);
-            for (String pckName : hiddenPackages)
-                System.out.println("Hidden: " + pckName);
-            for (String pckName : legacyProprietary)
-                System.out.println("Legacy proprietary: " + pckName);
-            for (String pckName : documented)
-                System.out.println("Documented: " + pckName);
-        }
-    }
-
-    void writeClass(final Pool pool, final ClassSymbol cs, final ClassWriter writer)
-        throws IOException
-    {
-        try {
-            pool.reset();
-            cs.pool = pool;
-            writer.writeClass(cs);
-            for (Symbol sym : cs.members().getSymbols(NON_RECURSIVE)) {
-                if (sym.kind == TYP) {
-                    ClassSymbol nestedClass = (ClassSymbol)sym;
-                    nestedClass.complete();
-                    writeClass(pool, nestedClass, writer);
-                }
-            }
-        } catch (ClassWriter.StringOverflow | ClassWriter.PoolOverflow ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @DefinedBy(Api.ANNOTATION_PROCESSING)
-    public SourceVersion getSupportedSourceVersion() {
-        return SourceVersion.latest();
-    }
-
-    // used for debugging
-    public static void main(String... args) {
-        String rt_jar = args[0];
-        String dest = args[1];
-        args = new String[] {
-            "-Xbootclasspath:" + rt_jar,
-            "-XDprocess.packages",
-            "-proc:only",
-            "-processor",
-            "com.sun.tools.javac.sym.CreateSymbols",
-            "-Acom.sun.tools.javac.sym.Jar=" + rt_jar,
-            "-Acom.sun.tools.javac.sym.Dest=" + dest,
-            // <editor-fold defaultstate="collapsed">
-            "java.applet",
-            "java.awt",
-            "java.awt.color",
-            "java.awt.datatransfer",
-            "java.awt.dnd",
-            "java.awt.event",
-            "java.awt.font",
-            "java.awt.geom",
-            "java.awt.im",
-            "java.awt.im.spi",
-            "java.awt.image",
-            "java.awt.image.renderable",
-            "java.awt.print",
-            "java.beans",
-            "java.beans.beancontext",
-            "java.io",
-            "java.lang",
-            "java.lang.annotation",
-            "java.lang.instrument",
-            "java.lang.management",
-            "java.lang.ref",
-            "java.lang.reflect",
-            "java.math",
-            "java.net",
-            "java.nio",
-            "java.nio.channels",
-            "java.nio.channels.spi",
-            "java.nio.charset",
-            "java.nio.charset.spi",
-            "java.rmi",
-            "java.rmi.activation",
-            "java.rmi.dgc",
-            "java.rmi.registry",
-            "java.rmi.server",
-            "java.security",
-            "java.security.acl",
-            "java.security.cert",
-            "java.security.interfaces",
-            "java.security.spec",
-            "java.sql",
-            "java.text",
-            "java.text.spi",
-            "java.util",
-            "java.util.concurrent",
-            "java.util.concurrent.atomic",
-            "java.util.concurrent.locks",
-            "java.util.jar",
-            "java.util.logging",
-            "java.util.prefs",
-            "java.util.regex",
-            "java.util.spi",
-            "java.util.zip",
-            "javax.accessibility",
-            "javax.activation",
-            "javax.activity",
-            "javax.annotation",
-            "javax.annotation.processing",
-            "javax.crypto",
-            "javax.crypto.interfaces",
-            "javax.crypto.spec",
-            "javax.imageio",
-            "javax.imageio.event",
-            "javax.imageio.metadata",
-            "javax.imageio.plugins.jpeg",
-            "javax.imageio.plugins.bmp",
-            "javax.imageio.spi",
-            "javax.imageio.stream",
-            "javax.jws",
-            "javax.jws.soap",
-            "javax.lang.model",
-            "javax.lang.model.element",
-            "javax.lang.model.type",
-            "javax.lang.model.util",
-            "javax.management",
-            "javax.management.loading",
-            "javax.management.monitor",
-            "javax.management.relation",
-            "javax.management.openmbean",
-            "javax.management.timer",
-            "javax.management.modelmbean",
-            "javax.management.remote",
-            "javax.management.remote.rmi",
-            "javax.naming",
-            "javax.naming.directory",
-            "javax.naming.event",
-            "javax.naming.ldap",
-            "javax.naming.spi",
-            "javax.net",
-            "javax.net.ssl",
-            "javax.print",
-            "javax.print.attribute",
-            "javax.print.attribute.standard",
-            "javax.print.event",
-            "javax.rmi",
-            "javax.rmi.CORBA",
-            "javax.rmi.ssl",
-            "javax.script",
-            "javax.security.auth",
-            "javax.security.auth.callback",
-            "javax.security.auth.kerberos",
-            "javax.security.auth.login",
-            "javax.security.auth.spi",
-            "javax.security.auth.x500",
-            "javax.security.cert",
-            "javax.security.sasl",
-            "javax.sound.sampled",
-            "javax.sound.sampled.spi",
-            "javax.sound.midi",
-            "javax.sound.midi.spi",
-            "javax.sql",
-            "javax.sql.rowset",
-            "javax.sql.rowset.serial",
-            "javax.sql.rowset.spi",
-            "javax.swing",
-            "javax.swing.border",
-            "javax.swing.colorchooser",
-            "javax.swing.filechooser",
-            "javax.swing.event",
-            "javax.swing.table",
-            "javax.swing.text",
-            "javax.swing.text.html",
-            "javax.swing.text.html.parser",
-            "javax.swing.text.rtf",
-            "javax.swing.tree",
-            "javax.swing.undo",
-            "javax.swing.plaf",
-            "javax.swing.plaf.basic",
-            "javax.swing.plaf.metal",
-            "javax.swing.plaf.multi",
-            "javax.swing.plaf.synth",
-            "javax.tools",
-            "javax.transaction",
-            "javax.transaction.xa",
-            "javax.xml.parsers",
-            "javax.xml.bind",
-            "javax.xml.bind.annotation",
-            "javax.xml.bind.annotation.adapters",
-            "javax.xml.bind.attachment",
-            "javax.xml.bind.helpers",
-            "javax.xml.bind.util",
-            "javax.xml.soap",
-            "javax.xml.ws",
-            "javax.xml.ws.handler",
-            "javax.xml.ws.handler.soap",
-            "javax.xml.ws.http",
-            "javax.xml.ws.soap",
-            "javax.xml.ws.spi",
-            "javax.xml.transform",
-            "javax.xml.transform.sax",
-            "javax.xml.transform.dom",
-            "javax.xml.transform.stax",
-            "javax.xml.transform.stream",
-            "javax.xml",
-            "javax.xml.crypto",
-            "javax.xml.crypto.dom",
-            "javax.xml.crypto.dsig",
-            "javax.xml.crypto.dsig.dom",
-            "javax.xml.crypto.dsig.keyinfo",
-            "javax.xml.crypto.dsig.spec",
-            "javax.xml.datatype",
-            "javax.xml.validation",
-            "javax.xml.namespace",
-            "javax.xml.xpath",
-            "javax.xml.stream",
-            "javax.xml.stream.events",
-            "javax.xml.stream.util",
-            "org.ietf.jgss",
-            "org.omg.CORBA",
-            "org.omg.CORBA.DynAnyPackage",
-            "org.omg.CORBA.ORBPackage",
-            "org.omg.CORBA.TypeCodePackage",
-            "org.omg.stub.java.rmi",
-            "org.omg.CORBA.portable",
-            "org.omg.CORBA_2_3",
-            "org.omg.CORBA_2_3.portable",
-            "org.omg.CosNaming",
-            "org.omg.CosNaming.NamingContextExtPackage",
-            "org.omg.CosNaming.NamingContextPackage",
-            "org.omg.SendingContext",
-            "org.omg.PortableServer",
-            "org.omg.PortableServer.CurrentPackage",
-            "org.omg.PortableServer.POAPackage",
-            "org.omg.PortableServer.POAManagerPackage",
-            "org.omg.PortableServer.ServantLocatorPackage",
-            "org.omg.PortableServer.portable",
-            "org.omg.PortableInterceptor",
-            "org.omg.PortableInterceptor.ORBInitInfoPackage",
-            "org.omg.Messaging",
-            "org.omg.IOP",
-            "org.omg.IOP.CodecFactoryPackage",
-            "org.omg.IOP.CodecPackage",
-            "org.omg.Dynamic",
-            "org.omg.DynamicAny",
-            "org.omg.DynamicAny.DynAnyPackage",
-            "org.omg.DynamicAny.DynAnyFactoryPackage",
-            "org.w3c.dom",
-            "org.w3c.dom.events",
-            "org.w3c.dom.bootstrap",
-            "org.w3c.dom.ls",
-            "org.xml.sax",
-            "org.xml.sax.ext",
-            "org.xml.sax.helpers",
-            "org.w3c.dom",
-            "org.w3c.dom.bootstrap",
-            "org.w3c.dom.ls",
-            "org.w3c.dom.ranges",
-            "org.w3c.dom.traversal",
-            "org.w3c.dom.html",
-            "org.w3c.dom.stylesheets",
-            "org.w3c.dom.css",
-            "org.w3c.dom.events",
-            "org.w3c.dom.views",
-            "com.sun.management",
-            "com.sun.security.auth",
-            "com.sun.security.auth.callback",
-            "com.sun.security.auth.login",
-            "com.sun.security.auth.module",
-            "com.sun.security.jgss",
-            "com.sun.net.httpserver",
-            "com.sun.net.httpserver.spi",
-            "javax.smartcardio"
-            // </editor-fold>
-        };
-        com.sun.tools.javac.Main.compile(args);
-    }
-
-}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java
deleted file mode 100644
index 6e8d447..0000000
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.sym;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import com.sun.tools.javac.util.Assert;
-
-/**
- * Provide details about profile contents.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own
- * risk.  This code and its internal interfaces are subject to change
- * or deletion without notice.</b></p>
- */
-public abstract class Profiles {
-    // for debugging
-    public static void main(String[] args) throws IOException {
-        Profiles p = Profiles.read(new File(args[0]));
-        if (args.length >= 2) {
-            Map<Integer,Set<String>> lists = new TreeMap<>();
-            for (int i = 1; i <= 4; i++)
-                lists.put(i, new TreeSet<String>());
-
-            File rt_jar_lst = new File(args[1]);
-            for (String line: Files.readAllLines(rt_jar_lst.toPath(), Charset.defaultCharset())) {
-                if (line.endsWith(".class")) {
-                    String type = line.substring(0, line.length() - 6);
-                    int profile = p.getProfile(type);
-                    for (int i = profile; i <= 4; i++)
-                        lists.get(i).add(type);
-                }
-            }
-
-            for (int i = 1; i <= 4; i++) {
-                try (BufferedWriter out = new BufferedWriter(new FileWriter(i + ".txt"))) {
-                    for (String type : lists.get(i)) {
-                        out.write(type);
-                        out.newLine();
-                    }
-                }
-            }
-        }
-    }
-
-    public static Profiles read(File file) throws IOException {
-        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
-            Properties p = new Properties();
-            p.load(in);
-            if (p.containsKey("java/lang/Object"))
-                return new SimpleProfiles(p);
-            else
-                return new MakefileProfiles(p);
-        }
-    }
-
-    public abstract int getProfileCount();
-
-    public abstract int getProfile(String typeName);
-
-    public abstract Set<String> getPackages(int profile);
-
-    private static class MakefileProfiles extends Profiles {
-        static class Package {
-            final Package parent;
-            final String name;
-
-            Map<String, Package> subpackages = new TreeMap<>();
-
-            int profile;
-            Map<String, Integer> includedTypes = new TreeMap<>();
-            Map<String, Integer> excludedTypes = new TreeMap<>();
-
-            Package(Package parent, String name) {
-                this.parent = parent;
-                this.name = name;
-            }
-
-            int getProfile() {
-                return (parent == null) ? profile : Math.max(parent.getProfile(), profile);
-            }
-
-            int getProfile(String simpleTypeName) {
-                Integer i;
-                if ((i = includedTypes.get(simpleTypeName)) != null)
-                    return i;
-                if ((i = includedTypes.get("*")) != null)
-                    return i;
-                if ((i = excludedTypes.get(simpleTypeName)) != null)
-                    return i + 1;
-                if ((i = excludedTypes.get("*")) != null)
-                    return i + 1;
-                return getProfile();
-            }
-
-            String getName() {
-                return (parent == null) ? name : (parent.getName() + "/" + name);
-            }
-
-            void getPackages(int profile, Set<String> results) {
-                int prf = getProfile();
-                if (prf != 0 && profile >= prf)
-                    results.add(getName());
-                for (Package pkg: subpackages.values())
-                    pkg.getPackages(profile, results);
-            }
-        }
-
-        final Map<String, Package> packages = new TreeMap<>();
-
-        final int maxProfile = 4;  // Three compact profiles plus full JRE
-
-        MakefileProfiles(Properties p) {
-            // consider crypto, only if java/lang package exists
-            boolean foundJavaLang = false;
-            for (int profile = 1; profile <= maxProfile; profile++) {
-                String prefix = (profile < maxProfile ? "PROFILE_" + profile : "FULL_JRE");
-                String inclPackages = p.getProperty(prefix + "_RTJAR_INCLUDE_PACKAGES");
-                if (inclPackages == null)
-                    break;
-                for (String pkg: inclPackages.substring(1).trim().split("\\s+")) {
-                    if (pkg.endsWith("/"))
-                        pkg = pkg.substring(0, pkg.length() - 1);
-                    if (foundJavaLang == false && pkg.equals("java/lang"))
-                        foundJavaLang = true;
-                    includePackage(profile, pkg);
-                }
-                String inclTypes =  p.getProperty(prefix + "_RTJAR_INCLUDE_TYPES");
-                if (inclTypes != null) {
-                    for (String type: inclTypes.replace("$$", "$").split("\\s+")) {
-                        if (type.endsWith(".class"))
-                            includeType(profile, type.substring(0, type.length() - 6));
-                    }
-                }
-                String exclTypes =  p.getProperty(prefix + "_RTJAR_EXCLUDE_TYPES");
-                if (exclTypes != null) {
-                    for (String type: exclTypes.replace("$$", "$").split("\\s+")) {
-                        if (type.endsWith(".class"))
-                            excludeType(profile, type.substring(0, type.length() - 6));
-                    }
-                }
-            }
-            /*
-             * A hack to force javax/crypto package into the compact1 profile,
-             * because this package exists in jce.jar, and therefore not in
-             * ct.sym. Note javax/crypto should exist in a profile along with
-             * javax/net/ssl package. Thus, this package is added to compact1,
-             * implying that it should exist in all three profiles.
-             */
-            if (foundJavaLang)
-                includePackage(1, "javax/crypto");
-        }
-
-        @Override
-        public int getProfileCount() {
-            return maxProfile;
-        }
-
-        @Override
-        public int getProfile(String typeName) {
-            int sep = typeName.lastIndexOf("/");
-            String packageName = typeName.substring(0, sep);
-            String simpleName = typeName.substring(sep + 1);
-
-            Package p = getPackage(packageName);
-            return p.getProfile(simpleName);
-        }
-
-        @Override
-        public Set<String> getPackages(int profile) {
-            Set<String> results = new TreeSet<>();
-            for (Package p: packages.values())
-                p.getPackages(profile, results);
-            return results;
-        }
-
-        private void includePackage(int profile, String packageName) {
-//            System.err.println("include package " + packageName);
-            Package p = getPackage(packageName);
-            Assert.check(p.profile == 0);
-            p.profile = profile;
-        }
-
-        private void includeType(int profile, String typeName) {
-//            System.err.println("include type " + typeName);
-            int sep = typeName.lastIndexOf("/");
-            String packageName = typeName.substring(0, sep);
-            String simpleName = typeName.substring(sep + 1);
-
-            Package p = getPackage(packageName);
-            Assert.check(!p.includedTypes.containsKey(simpleName));
-            p.includedTypes.put(simpleName, profile);
-        }
-
-        private void excludeType(int profile, String typeName) {
-//            System.err.println("exclude type " + typeName);
-            int sep = typeName.lastIndexOf("/");
-            String packageName = typeName.substring(0, sep);
-            String simpleName = typeName.substring(sep + 1);
-
-            Package p = getPackage(packageName);
-            Assert.check(!p.excludedTypes.containsKey(simpleName));
-            p.excludedTypes.put(simpleName, profile);
-        }
-
-        private Package getPackage(String packageName) {
-            int sep = packageName.lastIndexOf("/");
-            Package parent;
-            Map<String, Package> parentSubpackages;
-            String simpleName;
-            if (sep == -1) {
-                parent = null;
-                parentSubpackages = packages;
-                simpleName = packageName;
-            } else {
-                parent = getPackage(packageName.substring(0, sep));
-                parentSubpackages = parent.subpackages;
-                simpleName = packageName.substring(sep + 1);
-            }
-
-            Package p = parentSubpackages.get(simpleName);
-            if (p == null) {
-                parentSubpackages.put(simpleName, p = new Package(parent, simpleName));
-            }
-            return p;
-        }
-    }
-
-    private static class SimpleProfiles extends Profiles {
-        private final Map<String, Integer> map;
-        private final int profileCount;
-
-        SimpleProfiles(Properties p) {
-            int max = 0;
-            map = new HashMap<>();
-            for (Map.Entry<Object,Object> e: p.entrySet()) {
-                String typeName = (String) e.getKey();
-                int profile = Integer.valueOf((String) e.getValue());
-                map.put(typeName, profile);
-                max = Math.max(max, profile);
-            }
-            profileCount = max;
-        }
-
-        @Override
-        public int getProfileCount() {
-            return profileCount;
-        }
-
-        @Override
-        public int getProfile(String typeName) {
-            return map.get(typeName);
-        }
-
-        @Override
-        public Set<String> getPackages(int profile) {
-            Set<String> results = new TreeSet<>();
-            for (Map.Entry<String,Integer> e: map.entrySet()) {
-                String tn = e.getKey();
-                int prf = e.getValue();
-                int sep = tn.lastIndexOf("/");
-                if (sep > 0 && profile >= prf)
-                    results.add(tn);
-            }
-            return results;
-        }
-    }
-}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
index 3016af5..2787963 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
@@ -35,14 +35,20 @@
 
 import com.sun.source.tree.*;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Directive.RequiresDirective;
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
+
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
+import javax.tools.JavaFileManager.Location;
+
+import com.sun.tools.javac.code.Directive.ExportsDirective;
+
 /**
  * Root class for abstract syntax tree nodes. It provides definitions
  * for specific tree nodes as subclasses nested inside.
@@ -344,6 +350,12 @@
         DIV_ASG(DIV),                    // /=
         MOD_ASG(MOD),                    // %=
 
+        MODULEDEF,
+        EXPORTS,
+        PROVIDES,
+        REQUIRES,
+        USES,
+
         /** A synthetic let expression, of type LetExpr.
          */
         LETEXPR;                         // ala scheme
@@ -484,8 +496,12 @@
     public static class JCCompilationUnit extends JCTree implements CompilationUnitTree {
         /** All definitions in this file (ClassDef, Import, and Skip) */
         public List<JCTree> defs;
-        /* The source file name. */
+        /** The source file name. */
         public JavaFileObject sourcefile;
+        /** The module to which this compilation unit belongs. */
+        public ModuleSymbol modle;
+        /** The location in which this compilation unit was found. */
+        public Location locn;
         /** The package to which this compilation unit belongs. */
         public PackageSymbol packge;
         /** A scope containing top level classes. */
@@ -2593,8 +2609,202 @@
         }
     }
 
+    public static abstract class JCDirective extends JCTree
+        implements DirectiveTree {
+    }
+
+    public static class JCModuleDecl extends JCTree implements ModuleTree {
+        public JCExpression qualId;
+        public List<JCDirective> directives;
+        public ModuleSymbol sym;
+
+        protected JCModuleDecl(JCExpression qualId, List<JCDirective> directives) {
+            this.qualId = qualId;
+            this.directives = directives;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitModuleDef(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.MODULE;
+        }
+
+//        @Override
+        public JCExpression getName() {
+            return qualId;
+        }
+
+        @Override
+        public List<JCDirective> getDirectives() {
+            return directives;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitModule(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return MODULEDEF;
+        }
+    }
+
+    public static class JCExports extends JCDirective
+            implements ExportsTree {
+        public JCExpression qualid;
+        public List<JCExpression> moduleNames;
+        public ExportsDirective directive;
+
+        protected JCExports(JCExpression qualId, List<JCExpression> moduleNames) {
+            this.qualid = qualId;
+            this.moduleNames = moduleNames;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitExports(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.EXPORTS;
+        }
+
+        @Override
+        public JCExpression getExportName() {
+            return qualid;
+        }
+
+        @Override
+        public List<JCExpression> getModuleNames() {
+            return moduleNames;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitExports(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return EXPORTS;
+        }
+    }
+
+    public static class JCProvides extends JCDirective
+            implements ProvidesTree {
+        public JCExpression serviceName;
+        public JCExpression implName;
+
+        protected JCProvides(JCExpression serviceName, JCExpression implName) {
+            this.serviceName = serviceName;
+            this.implName = implName;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitProvides(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.PROVIDES;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitProvides(this, d);
+        }
+
+        @Override
+        public JCExpression getServiceName() {
+            return serviceName;
+        }
+
+        @Override
+        public JCExpression getImplementationName() {
+            return implName;
+        }
+
+        @Override
+        public Tag getTag() {
+            return PROVIDES;
+        }
+    }
+
+    public static class JCRequires extends JCDirective
+            implements RequiresTree {
+        public boolean isPublic;
+        public JCExpression moduleName;
+        public RequiresDirective directive;
+
+        protected JCRequires(boolean isPublic, JCExpression moduleName) {
+            this.isPublic = isPublic;
+            this.moduleName = moduleName;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitRequires(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.REQUIRES;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitRequires(this, d);
+        }
+
+        @Override
+        public boolean isPublic() {
+            return isPublic;
+        }
+
+        @Override
+        public JCExpression getModuleName() {
+            return moduleName;
+        }
+
+        @Override
+        public Tag getTag() {
+            return REQUIRES;
+        }
+    }
+
+    public static class JCUses extends JCDirective
+            implements UsesTree {
+        public JCExpression qualid;
+
+        protected JCUses(JCExpression qualId) {
+            this.qualid = qualId;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitUses(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.USES;
+        }
+
+        @Override
+        public JCExpression getServiceName() {
+            return qualid;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitUses(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return USES;
+        }
+    }
+
     public static class JCErroneous extends JCExpression
-            implements com.sun.source.tree.ErroneousTree {
+            implements ErroneousTree {
         public List<? extends JCTree> errs;
         protected JCErroneous(List<? extends JCTree> errs) {
             this.errs = errs;
@@ -2731,6 +2941,11 @@
         JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args);
         JCModifiers Modifiers(long flags, List<JCAnnotation> annotations);
         JCErroneous Erroneous(List<? extends JCTree> errs);
+        JCModuleDecl ModuleDef(JCExpression qualId, List<JCDirective> directives);
+        JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames);
+        JCProvides Provides(JCExpression serviceName, JCExpression implName);
+        JCRequires Requires(boolean isPublic, JCExpression qualId);
+        JCUses Uses(JCExpression qualId);
         LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr);
     }
 
@@ -2791,6 +3006,11 @@
         public void visitModifiers(JCModifiers that)         { visitTree(that); }
         public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); }
         public void visitErroneous(JCErroneous that)         { visitTree(that); }
+        public void visitModuleDef(JCModuleDecl that)        { visitTree(that); }
+        public void visitExports(JCExports that)             { visitTree(that); }
+        public void visitProvides(JCProvides that)           { visitTree(that); }
+        public void visitRequires(JCRequires that)           { visitTree(that); }
+        public void visitUses(JCUses that)                   { visitTree(that); }
         public void visitLetExpr(LetExpr that)               { visitTree(that); }
 
         public void visitTree(JCTree that)                   { Assert.error(); }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
index 15d9ca5..6457bc4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -438,6 +438,74 @@
         }
     }
 
+    @Override
+    public void visitModuleDef(JCModuleDecl tree) {
+        try {
+            print("module ");
+            printExpr(tree.qualId);
+            if (tree.directives == null) {
+                print(";");
+            } else {
+                printBlock(tree.directives);
+            }
+            println();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitExports(JCExports tree) {
+        try {
+            print("exports ");
+            printExpr(tree.qualid);
+            if (tree.moduleNames != null) {
+                print(" to ");
+                printExprs(tree.moduleNames);
+            }
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitProvides(JCProvides tree) {
+        try {
+            print("provides ");
+            printExpr(tree.serviceName);
+            print(" with ");
+            printExpr(tree.implName);
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitRequires(JCRequires tree) {
+        try {
+            print("requires ");
+            if (tree.isPublic)
+                print("public ");
+            printExpr(tree.moduleName);
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitUses(JCUses tree) {
+        try {
+            print("uses ");
+            printExpr(tree.qualid);
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
     public void visitImport(JCImport tree) {
         try {
             print("import ");
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
index e36cbaa..20638f7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -505,6 +505,44 @@
         return M.at(t.pos).Wildcard(kind, inner);
     }
 
+    @Override
+    public JCTree visitModule(ModuleTree node, P p) {
+        JCModuleDecl t = (JCModuleDecl) node;
+        JCExpression qualId = copy(t.qualId);
+        List<JCDirective> directives = copy(t.directives);
+        return M.at(t.pos).ModuleDef(qualId, directives);
+    }
+
+    @Override
+    public JCExports visitExports(ExportsTree node, P p) {
+        JCExports t = (JCExports) node;
+        JCExpression qualId = copy(t.qualid, p);
+        List<JCExpression> moduleNames = copy(t.moduleNames, p);
+        return M.at(t.pos).Exports(qualId, moduleNames);
+    }
+
+    @Override
+    public JCProvides visitProvides(ProvidesTree node, P p) {
+        JCProvides t = (JCProvides) node;
+        JCExpression serviceName = copy(t.serviceName, p);
+        JCExpression implName = copy(t.implName, p);
+        return M.at(t.pos).Provides(serviceName, implName);
+    }
+
+    @Override
+    public JCRequires visitRequires(RequiresTree node, P p) {
+        JCRequires t = (JCRequires) node;
+        JCExpression moduleName = copy(t.moduleName, p);
+        return M.at(t.pos).Requires(t.isPublic, moduleName);
+    }
+
+    @Override
+    public JCUses visitUses(UsesTree node, P p) {
+        JCUses t = (JCUses) node;
+        JCExpression serviceName = copy(t.qualid, p);
+        return M.at(t.pos).Uses(serviceName);
+    }
+
     @DefinedBy(Api.COMPILER_TREE)
     public JCTree visitOther(Tree node, P p) {
         JCTree tree = (JCTree) node;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
index af23690..e22fb64 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
@@ -42,6 +42,7 @@
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK;
 import static com.sun.tools.javac.tree.JCTree.Tag.SYNCHRONIZED;
+import javax.tools.JavaFileObject;
 
 /** Utility class containing inspector methods for trees.
  *
@@ -762,7 +763,12 @@
         node = skipParens(node);
         switch (node.getTag()) {
         case TOPLEVEL:
-            return ((JCCompilationUnit) node).packge;
+            JCCompilationUnit cut = (JCCompilationUnit) node;
+            if (isModuleInfo(cut) && cut.defs.nonEmpty() && cut.defs.head.hasTag(MODULEDEF))
+                return symbolFor(cut.defs.head);
+            return cut.packge;
+        case MODULEDEF:
+            return ((JCModuleDecl) node).sym;
         case PACKAGEDEF:
             return ((JCPackageDecl) node).packge;
         case CLASSDEF:
@@ -1144,4 +1150,21 @@
         finder.scan(e);
         return finder.foundTypeAnno;
     }
+
+    public static boolean isModuleInfo(JCCompilationUnit tree) {
+        return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE);
+    }
+
+    public static JCModuleDecl getModule(JCCompilationUnit t) {
+        if (t.defs.nonEmpty()) {
+            JCTree def = t.defs.head;
+            if (def.hasTag(MODULEDEF))
+                return (JCModuleDecl) def;
+        }
+        return null;
+    }
+
+    public static boolean isPackageInfo(JCCompilationUnit tree) {
+        return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
+    }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
index 959d812..59d3945 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
@@ -125,6 +125,7 @@
             Assert.check(node instanceof JCClassDecl
                 || node instanceof JCPackageDecl
                 || node instanceof JCImport
+                || node instanceof JCModuleDecl
                 || node instanceof JCSkip
                 || node instanceof JCErroneous
                 || (node instanceof JCExpressionStatement
@@ -536,6 +537,41 @@
         return Modifiers(flags, List.<JCAnnotation>nil());
     }
 
+    @Override
+    public JCModuleDecl ModuleDef(JCExpression qualid, List<JCDirective> directives) {
+        JCModuleDecl tree = new JCModuleDecl(qualid, directives);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames) {
+        JCExports tree = new JCExports(qualId, moduleNames);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCProvides Provides(JCExpression serviceName, JCExpression implName) {
+        JCProvides tree = new JCProvides(serviceName, implName);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCRequires Requires(boolean isPublic, JCExpression qualId) {
+        JCRequires tree = new JCRequires(isPublic, qualId);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCUses Uses(JCExpression qualId) {
+        JCUses tree = new JCUses(qualId);
+        tree.pos = pos;
+        return tree;
+    }
+
     public JCAnnotatedType AnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
         JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType);
         tree.pos = pos;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
index 2ef47d3..506925c 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,6 +71,34 @@
         scan(tree.pid);
     }
 
+    @Override
+    public void visitModuleDef(JCModuleDecl tree) {
+        scan(tree.qualId);
+        scan(tree.directives);
+    }
+
+    @Override
+    public void visitExports(JCExports tree) {
+        scan(tree.qualid);
+        scan(tree.moduleNames);
+    }
+
+    @Override
+    public void visitProvides(JCProvides tree) {
+        scan(tree.serviceName);
+        scan(tree.implName);
+    }
+
+    @Override
+    public void visitRequires(JCRequires tree) {
+        scan(tree.moduleName);
+    }
+
+    @Override
+    public void visitUses(JCUses tree) {
+        scan(tree.qualid);
+    }
+
     public void visitImport(JCImport tree) {
         scan(tree.qualid);
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java
new file mode 100644
index 0000000..2b34d09
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ModuleHelper {
+    /** The context key for the module helper. */
+    protected static final Context.Key<ModuleHelper> moduleHelperKey = new Context.Key<>();
+
+    /** Get the JavaCompiler instance for this context. */
+    public static ModuleHelper instance(Context context) {
+        ModuleHelper instance = context.get(moduleHelperKey);
+        if (instance == null)
+            instance = new ModuleHelper(context);
+        return instance;
+    }
+
+    public ModuleHelper(Context context) {
+        context.put(moduleHelperKey, this);
+        Options options = Options.instance(context);
+        allowAccessToInternalAPI = options.isSet("accessInternalAPI");
+    }
+
+    final boolean allowAccessToInternalAPI;
+
+    private void exportPackageToModule(String packageName, Object target)
+            throws ClassNotFoundException, NoSuchMethodException, IllegalArgumentException,
+                   InvocationTargetException, IllegalAccessException {
+        if (addExportsMethod == null) {
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            addExportsMethod = moduleClass.getDeclaredMethod("addExports",
+                    new Class<?>[] { String.class, moduleClass });
+        }
+        addExportsMethod.invoke(from, new Object[] { packageName, target });
+    }
+
+    static final String[] javacInternalPackages = new String[] {
+        "com.sun.tools.javac.api",
+        "com.sun.tools.javac.code",
+        "com.sun.tools.javac.comp",
+        "com.sun.tools.javac.file",
+        "com.sun.tools.javac.jvm",
+        "com.sun.tools.javac.main",
+        "com.sun.tools.javac.model",
+        "com.sun.tools.javac.parser",
+        "com.sun.tools.javac.platform",
+        "com.sun.tools.javac.processing",
+        "com.sun.tools.javac.tree",
+        "com.sun.tools.javac.util",
+
+        "com.sun.tools.doclint",
+    };
+
+    public void addExports(ClassLoader classLoader) {
+        try {
+            if (allowAccessToInternalAPI) {
+                if (from == null) {
+                    if (getModuleMethod == null) {
+                        getModuleMethod = Class.class.getDeclaredMethod("getModule", new Class<?>[0]);
+                    }
+                    from = getModuleMethod.invoke(getClass(), new Object[0]);
+                }
+                if (getUnnamedModuleMethod == null) {
+                    getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule", new Class<?>[0]);
+                }
+                Object target = getUnnamedModuleMethod.invoke(classLoader, new Object[0]);
+                for (String pack: javacInternalPackages) {
+                    exportPackageToModule(pack, target);
+                }
+            }
+        } catch (Exception e) {
+            // do nothing
+        }
+    }
+
+    // a module instance
+    private Object from = null;
+
+    // on java.lang.reflect.Module
+    private static Method addExportsMethod = null;
+
+    // on java.lang.ClassLoader
+    private static Method getUnnamedModuleMethod = null;
+
+    // on java.lang.Class
+    private static Method getModuleMethod = null;
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java
new file mode 100644
index 0000000..7e7accc
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.ServiceLoader;
+
+/** This class provides wrappers for classes and methods that are new in JDK 9, and which are not
+ *  available on older versions of the platform on which javac may be compiled and run.
+ *  In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers
+ *  can be replaced by use of the real underlying classes.
+ */
+public class ModuleWrappers {
+    public static final class ServiceLoaderHelper {
+        @SuppressWarnings("unchecked")
+        public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) {
+            try {
+                Class<?> layerClass = LayerHelper.getLayerClass();
+                Method loadMethod = ServiceLoader.class
+                        .getDeclaredMethod("load", layerClass, Class.class);
+                Object result = loadMethod.invoke(ServiceLoader.class, layer.theRealLayer, service);
+                return (ServiceLoader<S>)result;
+            } catch (NoSuchMethodException |
+                    SecurityException |
+                    IllegalArgumentException |
+                    IllegalAccessException |
+                    InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+    }
+
+    public static class ModuleFinder {
+        Object theRealModuleFinder;
+
+        private ModuleFinder(Object moduleFinder) {
+            this.theRealModuleFinder = moduleFinder;
+        }
+
+        public static ModuleFinder of(Path... dirs) {
+            try {
+                Object result = ModuleFinderHelper.getOfMethod()
+                        .invoke(ModuleFinderHelper.moduleFinderInterface, (Object)dirs);
+                ModuleFinder mFinder = new ModuleFinder(result);
+                return mFinder;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+        public static ModuleFinder empty() {
+            try {
+                Object result = ModuleFinderHelper.getEmptyMethod()
+                        .invoke(ModuleFinderHelper.moduleFinderInterface);
+                ModuleFinder mFinder = new ModuleFinder(result);
+                return mFinder;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+    }
+
+    private static class ModuleFinderHelper {
+        static Method ofMethod = null;
+        static Method emptyMethod = null;
+        static Class<?> moduleFinderInterface;
+
+        static Method getOfMethod() {
+            if (ModuleFinderHelper.ofMethod == null) {
+                try {
+                    getModuleFinderInterface();
+                    ofMethod = moduleFinderInterface.getDeclaredMethod("of", Path[].class);
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return ofMethod;
+        }
+
+        static Method getEmptyMethod() {
+            if (emptyMethod == null) {
+                try {
+                    getModuleFinderInterface();
+                    emptyMethod = moduleFinderInterface.getDeclaredMethod("empty");
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return emptyMethod;
+        }
+
+        static Class<?> getModuleFinderInterface() {
+            if (moduleFinderInterface == null) {
+                try {
+                    moduleFinderInterface = Class.forName("java.lang.module.ModuleFinder", false, ClassLoader.getSystemClassLoader());
+                } catch (ClassNotFoundException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return moduleFinderInterface;
+        }
+    }
+
+    public static final class Configuration {
+        Object theRealConfiguration;
+
+        private Configuration(Object configuration) {
+            this.theRealConfiguration = configuration;
+        }
+
+        public Configuration resolveRequiresAndUses(
+                ModuleFinder beforeFinder,
+                ModuleFinder afterFinder,
+                Collection<String> roots) {
+            try {
+                Object result = ConfigurationHelper.getResolveRequiresAndUses()
+                        .invoke(theRealConfiguration,
+                                    beforeFinder.theRealModuleFinder,
+                                    afterFinder.theRealModuleFinder,
+                                    roots
+                                );
+                Configuration configuration = new Configuration(result);
+                return configuration;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+    }
+
+    private static class ConfigurationHelper {
+        static Method resolveRequiresAndUsesMethod;
+        static Class<?> configurationClass;
+
+        static Method getResolveRequiresAndUses() {
+            if (resolveRequiresAndUsesMethod == null) {
+                try {
+                    getConfigurationClass();
+                    Class<?> moduleFinderInterface = ModuleFinderHelper.getModuleFinderInterface();
+                    Class<?> configurationClass = ConfigurationHelper.getConfigurationClass();
+                    resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses",
+                                moduleFinderInterface,
+                                moduleFinderInterface,
+                                Collection.class
+                    );
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return resolveRequiresAndUsesMethod;
+        }
+
+        static Class<?> getConfigurationClass() {
+            if (configurationClass == null) {
+                try {
+                    configurationClass = Class.forName("java.lang.module.Configuration", false, ClassLoader.getSystemClassLoader());
+                } catch (ClassNotFoundException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return configurationClass;
+        }
+    }
+
+    public static final class Layer {
+        Object theRealLayer;
+
+        private Layer(Object layer) {
+            this.theRealLayer = layer;
+        }
+
+        public static Layer boot() {
+            try {
+                Object result = LayerHelper.getBootMethod().invoke(LayerHelper.getLayerClass());
+                Layer layer = new Layer(result);
+                return layer;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+        public Configuration configuration() {
+            try {
+                Object result = LayerHelper.getConfigurationMethod().invoke(theRealLayer);
+                Layer layer = new Layer(result);
+                return new Configuration(result);
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+        public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) {
+            try {
+                Object result = LayerHelper.getDefineModulesWithOneLoaderMethod()
+                        .invoke(theRealLayer, configuration.theRealConfiguration, parentClassLoader);
+                Layer layer = new Layer(result);
+                return layer;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+    }
+
+    private static class LayerHelper {
+        static Class<?> layerClass;
+        static Method bootMethod;
+        static Method defineModulesWithOneLoaderMethod = null;
+        static Method configurationMethod;
+
+        static Class<?> getLayerClass() {
+            if (layerClass == null) {
+                try {
+                    layerClass = Class.forName("java.lang.reflect.Layer", false, ClassLoader.getSystemClassLoader());
+                } catch (ClassNotFoundException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return layerClass;
+        }
+
+        static Method getBootMethod() {
+            if (bootMethod == null) {
+                try {
+                    bootMethod = getLayerClass().getDeclaredMethod("boot");
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return bootMethod;
+        }
+
+        static Method getDefineModulesWithOneLoaderMethod() {
+            if (defineModulesWithOneLoaderMethod == null) {
+                try {
+                    defineModulesWithOneLoaderMethod = getLayerClass().getDeclaredMethod("defineModulesWithOneLoader",
+                                ConfigurationHelper.getConfigurationClass(),
+                                ClassLoader.class
+                    );
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return defineModulesWithOneLoaderMethod;
+        }
+
+        static Method getConfigurationMethod() {
+            if (configurationMethod == null) {
+                try {
+                    configurationMethod =  getLayerClass().getDeclaredMethod("configuration");
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return configurationMethod;
+        }
+    }
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
index b033f63..b1321f8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -127,9 +127,11 @@
         int prefixOffset   = prefix.getByteOffset();
         int prefixLength   = prefix.getByteLength();
 
+        if (thisLength < prefixLength)
+            return false;
+
         int i = 0;
         while (i < prefixLength &&
-               i < thisLength &&
                thisBytes[thisOffset + i] == prefixBytes[prefixOffset + i])
             i++;
         return i == prefixLength;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
index 2132774..63866a6 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -63,6 +63,13 @@
     public final Name _default;
     public final Name _super;
     public final Name _this;
+    public final Name exports;
+    public final Name module;
+    public final Name provides;
+    public final Name requires;
+    public final Name to;
+    public final Name uses;
+    public final Name with;
 
     // field and method names
     public final Name _name;
@@ -116,6 +123,9 @@
     // package names
     public final Name java_lang;
 
+    // module names
+    public final Name java_base;
+
     // attribute names
     public final Name Annotation;
     public final Name AnnotationDefault;
@@ -134,6 +144,7 @@
     public final Name LocalVariableTable;
     public final Name LocalVariableTypeTable;
     public final Name MethodParameters;
+    public final Name Module;
     public final Name RuntimeInvisibleAnnotations;
     public final Name RuntimeInvisibleParameterAnnotations;
     public final Name RuntimeInvisibleTypeAnnotations;
@@ -148,6 +159,7 @@
     public final Name Synthetic;
     public final Name Value;
     public final Name Varargs;
+    public final Name Version;
 
     // members of java.lang.annotation.ElementType
     public final Name ANNOTATION_TYPE;
@@ -170,10 +182,11 @@
     public final Name T;
     public final Name deprecated;
     public final Name ex;
+    public final Name module_info;
     public final Name package_info;
     public final Name requireNonNull;
 
-    //lambda-related
+    // lambda-related
     public final Name lambda;
     public final Name metafactory;
     public final Name altMetafactory;
@@ -205,6 +218,13 @@
         _default = fromString("default");
         _super = fromString("super");
         _this = fromString("this");
+        exports = fromString("exports");
+        module = fromString("module");
+        provides = fromString("provides");
+        requires = fromString("requires");
+        to = fromString("to");
+        uses = fromString("uses");
+        with = fromString("with");
 
         // field and method names
         _name = fromString("name");
@@ -259,6 +279,9 @@
         // package names
         java_lang = fromString("java.lang");
 
+        // module names
+        java_base = fromString("java.base");
+
         // attribute names
         Annotation = fromString("Annotation");
         AnnotationDefault = fromString("AnnotationDefault");
@@ -277,6 +300,7 @@
         LocalVariableTable = fromString("LocalVariableTable");
         LocalVariableTypeTable = fromString("LocalVariableTypeTable");
         MethodParameters = fromString("MethodParameters");
+        Module = fromString("Module");
         RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
         RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
         RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
@@ -291,6 +315,7 @@
         Synthetic = fromString("Synthetic");
         Value = fromString("Value");
         Varargs = fromString("Varargs");
+        Version = fromString("Version");
 
         // members of java.lang.annotation.ElementType
         ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
@@ -313,6 +338,7 @@
         T = fromString("T");
         deprecated = fromString("deprecated");
         ex = fromString("ex");
+        module_info = fromString("module-info");
         package_info = fromString("package-info");
         requireNonNull = fromString("requireNonNull");
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ServiceLoader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ServiceLoader.java
deleted file mode 100644
index 9820ebe..0000000
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ServiceLoader.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.ServiceConfigurationError;
-
-
-/**
- * This is a temporary, modified copy of java.util.ServiceLoader, for use by
- * javac, to work around bug JDK-8004082.
- *
- * The bug describes problems in the interaction between ServiceLoader and
- * URLClassLoader, such that references to a jar file passed to URLClassLoader
- * may be retained after calling URLClassLoader.close(), preventing the jar
- * file from being deleted on Windows.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-
-public final class ServiceLoader<S>
-    implements Iterable<S>
-{
-
-    private static final String PREFIX = "META-INF/services/";
-
-    // The class or interface representing the service being loaded
-    private Class<S> service;
-
-    // The class loader used to locate, load, and instantiate providers
-    private ClassLoader loader;
-
-    // Cached providers, in instantiation order
-    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
-
-    // The current lazy-lookup iterator
-    private LazyIterator lookupIterator;
-
-    /**
-     * Clear this loader's provider cache so that all providers will be
-     * reloaded.
-     *
-     * <p> After invoking this method, subsequent invocations of the {@link
-     * #iterator() iterator} method will lazily look up and instantiate
-     * providers from scratch, just as is done by a newly-created loader.
-     *
-     * <p> This method is intended for use in situations in which new providers
-     * can be installed into a running Java virtual machine.
-     */
-    public void reload() {
-        providers.clear();
-        lookupIterator = new LazyIterator(service, loader);
-    }
-
-    private ServiceLoader(Class<S> svc, ClassLoader cl) {
-        service = Objects.requireNonNull(svc, "Service interface cannot be null");
-        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
-        reload();
-    }
-
-    private static void fail(Class<?> service, String msg, Throwable cause)
-        throws ServiceConfigurationError
-    {
-        throw new ServiceConfigurationError(service.getName() + ": " + msg,
-                                            cause);
-    }
-
-    private static void fail(Class<?> service, String msg)
-        throws ServiceConfigurationError
-    {
-        throw new ServiceConfigurationError(service.getName() + ": " + msg);
-    }
-
-    private static void fail(Class<?> service, URL u, int line, String msg)
-        throws ServiceConfigurationError
-    {
-        fail(service, u + ":" + line + ": " + msg);
-    }
-
-    // Parse a single line from the given configuration file, adding the name
-    // on the line to the names list.
-    //
-    private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
-                          List<String> names)
-        throws IOException, ServiceConfigurationError
-    {
-        String ln = r.readLine();
-        if (ln == null) {
-            return -1;
-        }
-        int ci = ln.indexOf('#');
-        if (ci >= 0) ln = ln.substring(0, ci);
-        ln = ln.trim();
-        int n = ln.length();
-        if (n != 0) {
-            if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
-                fail(service, u, lc, "Illegal configuration-file syntax");
-            int cp = ln.codePointAt(0);
-            if (!Character.isJavaIdentifierStart(cp))
-                fail(service, u, lc, "Illegal provider-class name: " + ln);
-            for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
-                cp = ln.codePointAt(i);
-                if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
-                    fail(service, u, lc, "Illegal provider-class name: " + ln);
-            }
-            if (!providers.containsKey(ln) && !names.contains(ln))
-                names.add(ln);
-        }
-        return lc + 1;
-    }
-
-    // Parse the content of the given URL as a provider-configuration file.
-    //
-    // @param  service
-    //         The service type for which providers are being sought;
-    //         used to construct error detail strings
-    //
-    // @param  u
-    //         The URL naming the configuration file to be parsed
-    //
-    // @return A (possibly empty) iterator that will yield the provider-class
-    //         names in the given configuration file that are not yet members
-    //         of the returned set
-    //
-    // @throws ServiceConfigurationError
-    //         If an I/O error occurs while reading from the given URL, or
-    //         if a configuration-file format error is detected
-    //
-    private Iterator<String> parse(Class<?> service, URL u)
-        throws ServiceConfigurationError
-    {
-        InputStream in = null;
-        ArrayList<String> names = new ArrayList<>();
-        try {
-            // The problem is that by default, streams opened with
-            // u.openInputStream use a cached reference to a JarFile, which
-            // is separate from the reference used by URLClassLoader, and
-            // which is not closed by URLClassLoader.close().
-            // The workaround is to disable caching for this specific jar file,
-            // so that the reference to the jar file can be closed when the
-            // file has been read.
-            // Original code:
-            // in = u.openStream();
-            // Workaround ...
-            URLConnection uc = u.openConnection();
-            uc.setUseCaches(false);
-            in = uc.getInputStream();
-            // ... end of workaround.
-            try (BufferedReader r = new BufferedReader(new InputStreamReader(in, "utf-8"))) {
-                int lc = 1;
-                while ((lc = parseLine(service, u, r, lc, names)) >= 0);
-            }
-        } catch (IOException x) {
-            fail(service, "Error reading configuration file", x);
-        } finally {
-            try {
-                if (in != null) in.close();
-            } catch (IOException y) {
-                fail(service, "Error closing configuration file", y);
-            }
-        }
-        return names.iterator();
-    }
-
-    // Private inner class implementing fully-lazy provider lookup
-    //
-    private class LazyIterator
-        implements Iterator<S>
-    {
-
-        Class<S> service;
-        ClassLoader loader;
-        Enumeration<URL> configs = null;
-        Iterator<String> pending = null;
-        String nextName = null;
-
-        private LazyIterator(Class<S> service, ClassLoader loader) {
-            this.service = service;
-            this.loader = loader;
-        }
-
-        public boolean hasNext() {
-            if (nextName != null) {
-                return true;
-            }
-            if (configs == null) {
-                try {
-                    String fullName = PREFIX + service.getName();
-                    if (loader == null)
-                        configs = ClassLoader.getSystemResources(fullName);
-                    else
-                        configs = loader.getResources(fullName);
-                } catch (IOException x) {
-                    fail(service, "Error locating configuration files", x);
-                }
-            }
-            while ((pending == null) || !pending.hasNext()) {
-                if (!configs.hasMoreElements()) {
-                    return false;
-                }
-                pending = parse(service, configs.nextElement());
-            }
-            nextName = pending.next();
-            return true;
-        }
-
-        public S next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            String cn = nextName;
-            nextName = null;
-            Class<?> c = null;
-            try {
-                c = Class.forName(cn, false, loader);
-            } catch (ClassNotFoundException x) {
-                fail(service,
-                     "Provider " + cn + " not found");
-            }
-            if (!service.isAssignableFrom(c)) {
-                fail(service,
-                     "Provider " + cn  + " not a subtype");
-            }
-            try {
-                S p = service.cast(c.newInstance());
-                providers.put(cn, p);
-                return p;
-            } catch (Throwable x) {
-                fail(service,
-                     "Provider " + cn + " could not be instantiated: " + x,
-                     x);
-            }
-            throw new Error();          // This cannot happen
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-    /**
-     * Lazily loads the available providers of this loader's service.
-     *
-     * <p> The iterator returned by this method first yields all of the
-     * elements of the provider cache, in instantiation order.  It then lazily
-     * loads and instantiates any remaining providers, adding each one to the
-     * cache in turn.
-     *
-     * <p> To achieve laziness the actual work of parsing the available
-     * provider-configuration files and instantiating providers must be done by
-     * the iterator itself.  Its {@link java.util.Iterator#hasNext hasNext} and
-     * {@link java.util.Iterator#next next} methods can therefore throw a
-     * {@link ServiceConfigurationError} if a provider-configuration file
-     * violates the specified format, or if it names a provider class that
-     * cannot be found and instantiated, or if the result of instantiating the
-     * class is not assignable to the service type, or if any other kind of
-     * exception or error is thrown as the next provider is located and
-     * instantiated.  To write robust code it is only necessary to catch {@link
-     * ServiceConfigurationError} when using a service iterator.
-     *
-     * <p> If such an error is thrown then subsequent invocations of the
-     * iterator will make a best effort to locate and instantiate the next
-     * available provider, but in general such recovery cannot be guaranteed.
-     *
-     * <blockquote style="font-size: smaller; line-height: 1.2"><span
-     * style="padding-right: 1em; font-weight: bold">Design Note</span>
-     * Throwing an error in these cases may seem extreme.  The rationale for
-     * this behavior is that a malformed provider-configuration file, like a
-     * malformed class file, indicates a serious problem with the way the Java
-     * virtual machine is configured or is being used.  As such it is
-     * preferable to throw an error rather than try to recover or, even worse,
-     * fail silently.</blockquote>
-     *
-     * <p> The iterator returned by this method does not support removal.
-     * Invoking its {@link java.util.Iterator#remove() remove} method will
-     * cause an {@link UnsupportedOperationException} to be thrown.
-     *
-     * @return  An iterator that lazily loads providers for this loader's
-     *          service
-     */
-    public Iterator<S> iterator() {
-        return new Iterator<S>() {
-
-            Iterator<Map.Entry<String,S>> knownProviders
-                = providers.entrySet().iterator();
-
-            public boolean hasNext() {
-                if (knownProviders.hasNext())
-                    return true;
-                return lookupIterator.hasNext();
-            }
-
-            public S next() {
-                if (knownProviders.hasNext())
-                    return knownProviders.next().getValue();
-                return lookupIterator.next();
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-
-        };
-    }
-
-    /**
-     * Creates a new service loader for the given service type and class
-     * loader.
-     *
-     * @param  service
-     *         The interface or abstract class representing the service
-     *
-     * @param  loader
-     *         The class loader to be used to load provider-configuration files
-     *         and provider classes, or <tt>null</tt> if the system class
-     *         loader (or, failing that, the bootstrap class loader) is to be
-     *         used
-     *
-     * @return A new service loader
-     */
-    public static <S> ServiceLoader<S> load(Class<S> service,
-                                            ClassLoader loader)
-    {
-        return new ServiceLoader<>(service, loader);
-    }
-
-    /**
-     * Creates a new service loader for the given service type, using the
-     * current thread's {@linkplain java.lang.Thread#getContextClassLoader
-     * context class loader}.
-     *
-     * <p> An invocation of this convenience method of the form
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>)</pre></blockquote>
-     *
-     * is equivalent to
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>,
-     *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
-     *
-     * @param  service
-     *         The interface or abstract class representing the service
-     *
-     * @return A new service loader
-     */
-    public static <S> ServiceLoader<S> load(Class<S> service) {
-        ClassLoader cl = Thread.currentThread().getContextClassLoader();
-        return ServiceLoader.load(service, cl);
-    }
-
-    /**
-     * Creates a new service loader for the given service type, using the
-     * extension class loader.
-     *
-     * <p> This convenience method simply locates the extension class loader,
-     * call it <tt><i>extClassLoader</i></tt>, and then returns
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
-     *
-     * <p> If the extension class loader cannot be found then the system class
-     * loader is used; if there is no system class loader then the bootstrap
-     * class loader is used.
-     *
-     * <p> This method is intended for use when only installed providers are
-     * desired.  The resulting service will only find and load providers that
-     * have been installed into the current Java virtual machine; providers on
-     * the application's class path will be ignored.
-     *
-     * @param  service
-     *         The interface or abstract class representing the service
-     *
-     * @return A new service loader
-     */
-    public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
-        ClassLoader cl = ClassLoader.getSystemClassLoader();
-        ClassLoader prev = null;
-        while (cl != null) {
-            prev = cl;
-            cl = cl.getParent();
-        }
-        return ServiceLoader.load(service, prev);
-    }
-
-    /**
-     * Returns a string describing this service.
-     *
-     * @return  A descriptive string
-     */
-    public String toString() {
-        return "java.util.ServiceLoader[" + service.getName() + "]";
-    }
-
-}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
index 789069b..96d6dc1 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
@@ -497,7 +497,15 @@
         List<String> opts = new ArrayList<>();
         opts.add("-proc:only");
         opts.addAll(javac_extras);
-        CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null);
+
+        CompilationTask t;
+        try {
+            t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null);
+        } catch (IllegalArgumentException e) {
+            util.error("bad.arg", e.getMessage());
+            return false;
+        }
+
         JavahProcessor p = new JavahProcessor(g);
         t.setProcessors(Collections.singleton(p));
 
@@ -505,15 +513,7 @@
         if (p.exit != null)
             throw new Util.Exit(p.exit);
         return ok;
-    }
 
-    private List<File> pathToFiles(String path) {
-        List<File> files = new ArrayList<>();
-        for (String f: path.split(File.pathSeparator)) {
-            if (f.length() > 0)
-                files.add(new File(f));
-        }
-        return files;
     }
 
     static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties
index 875816b..6aa92c1 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties
@@ -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
@@ -35,6 +35,8 @@
 at.args.io.exception=\
         The following I/O problem was encountered when processing an @ \
         argument on the command line: {0}.
+bad.arg=\
+        Bad argument: {0}
 old.jni.mixed=\
         Can''t mix options -jni and -old.  Try -help.
 old.llni.mixed=\
@@ -78,7 +80,8 @@
 -help                 Print this help message and exit\n\t\
 -classpath <path>     Path from which to load classes\n\t\
 -cp <path>            Path from which to load classes\n\t\
--bootclasspath <path> Path from which to load bootstrap classes\n\t\
+-modulepath <path>    Path from which to load application modules\n\t\
+-system <path>        JDK directory from which to load system modules\n\t\
 -d <dir>              Output directory\n\t\
 -o <file>             Output file (only one of -d or -o may be used)\n\t\
 -jni                  Generate JNI-style header file (default)\n\t\
@@ -86,8 +89,10 @@
 -verbose              Enable verbose output\n\t\
 -force                Always write output files\n\
 \n\
-<classes> are specified with their fully qualified names (for\n\
-instance, java.lang.Object).\n
+<classes> are specified with their fully qualified names, optionally\n\
+prefixed by a module name followed by '/'. Examples:\n\
+    java.lang.Object\n\
+    java.base/java.io.File\n\
 
 main.usage=\
 Usage: \n\
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java
index 2bd1cac..d5cb4ea 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java
@@ -35,8 +35,10 @@
 import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.code.ClassFinder;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.sjavac.comp.PubapiVisitor;
@@ -77,10 +79,11 @@
     }
 
     public PubApi getPubApi(String fullyQualifiedClassName) {
+        Symtab syms = Symtab.instance(context);
         ClassFinder cr = ClassFinder.instance(context);
         Names ns = Names.instance(context);
         Name n = ns.fromString(fullyQualifiedClassName);
-        ClassSymbol cs = cr.loadClass(n);
+        ClassSymbol cs = cr.loadClass(syms.inferModule(Convert.packagePart(n)), n);
         PubapiVisitor v = new PubapiVisitor();
         v.visit(cs);
         return v.getCollectedPubApi();
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java
index b288955..83ebed6 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
index b1b7715..4c39a70 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
@@ -53,6 +53,7 @@
 import com.sun.tools.sjavac.options.Options;
 import com.sun.tools.sjavac.options.SourceLocation;
 import com.sun.tools.sjavac.server.Sjavac;
+import java.io.UncheckedIOException;
 
 import javax.tools.JavaFileManager;
 
@@ -123,8 +124,8 @@
             if (fileManager instanceof JavacFileManager) {
                 try {
                     ((JavacFileManager) fileManager).close();
-                } catch (IOException e) {
-                    return RC_FATAL;
+                } catch (IOException es) {
+                    throw new UncheckedIOException(es);
                 }
             }
             return result.exitCode;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java
index 496f039..5a67380 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -131,7 +133,7 @@
             return file;
         }
 
-        if (visibleSources.contains(file.toUri())) {
+        if (visibleSources.contains(file.toUri()) || isModuleInfo(file)) {
             return file;
         }
         return null;
@@ -166,12 +168,21 @@
             return file;
         }
 
-        if (visibleSources.contains(file.toUri())) {
+        if (visibleSources.contains(file.toUri()) || isModuleInfo(file)) {
             return file;
         }
         return null;
     }
 
+    private boolean isModuleInfo(FileObject fo) {
+        if (fo instanceof JavaFileObject) {
+            JavaFileObject jfo = (JavaFileObject) fo;
+            return jfo.isNameCompatible("module-info", Kind.SOURCE)
+                || jfo.isNameCompatible("module-info", Kind.CLASS);
+        }
+        return false;
+    }
+
     @Override @DefinedBy(Api.COMPILER)
     public FileObject getFileForOutput(Location location,
                                        String packageName,
@@ -192,6 +203,11 @@
         return file;
     }
 
+    @Override
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        return super.getModuleLocation(location, locUnwrap(fo), pkgName);
+    }
+
     private static String packageNameFromFileName(String fn) {
         StringBuilder sb = new StringBuilder();
         int p = fn.indexOf('_'), pp = 0;
diff --git a/langtools/src/jdk.compiler/share/classes/module-info.java b/langtools/src/jdk.compiler/share/classes/module-info.java
new file mode 100644
index 0000000..91a0e22
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/module-info.java
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * 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.compiler {
+    requires public java.compiler;
+
+    exports com.sun.source.doctree;
+    exports com.sun.source.tree;
+    exports com.sun.source.util;
+    exports com.sun.tools.javac;
+    exports com.sun.tools.javah;
+    exports com.sun.tools.doclint to
+        jdk.javadoc;
+    exports com.sun.tools.javac.api to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.code to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.comp to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.file to
+        jdk.jdeps,
+        jdk.javadoc;
+    exports com.sun.tools.javac.jvm to
+        jdk.javadoc;
+    exports com.sun.tools.javac.main to
+        jdk.javadoc;
+    exports com.sun.tools.javac.model to
+        jdk.javadoc;
+    exports com.sun.tools.javac.parser to
+        jdk.jshell;
+    exports com.sun.tools.javac.platform to
+        jdk.javadoc;
+    exports com.sun.tools.javac.tree to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.util to
+        jdk.jdeps,
+        jdk.javadoc,
+        jdk.jshell;
+
+    uses javax.annotation.processing.Processor;
+    uses com.sun.source.util.Plugin;
+    uses com.sun.tools.javac.platform.PlatformProvider;
+
+    provides com.sun.tools.javac.platform.PlatformProvider
+        with com.sun.tools.javac.platform.JDKPlatformProvider;
+
+    provides javax.tools.JavaCompiler
+        with com.sun.tools.javac.api.JavacTool;
+}
+
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java
index 9378865..3adbee4 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -155,15 +155,8 @@
             htmlTree.addStyle(HtmlStyle.indexNav);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
             addAllClassesLink(ul);
-            if (configuration.showProfiles) {
-                addAllProfilesLink(ul);
-            }
             htmlTree.addContent(ul);
             body.addContent(htmlTree);
-            if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
-                Content profileSummary = configuration.getResource("doclet.Profiles");
-                addProfilesList(profileSummary, body);
-            }
             addPackagesList(packages, text, tableSummary, body);
         }
     }
@@ -201,21 +194,4 @@
      */
     protected void addAllClassesLink(Content div) {
     }
-
-    /**
-     * Do nothing. This will be overridden.
-     *
-     * @param div the document tree to which the all profiles link will be added
-     */
-    protected void addAllProfilesLink(Content div) {
-    }
-
-    /**
-     * Do nothing. This will be overridden.
-     *
-     * @param profileSummary the profile summary heading
-     * @param body the content tree to which the profiles list will be added
-     */
-    protected void addProfilesList(Content profileSummary, Content body) {
-    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
index d9dafe9..6eac715 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
@@ -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,7 +28,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.javadoc.RootDocImpl;
 import com.sun.tools.doclets.formats.html.markup.*;
 import com.sun.tools.doclets.internal.toolkit.*;
@@ -173,23 +172,13 @@
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
-        if (configuration.showProfiles) {
-            String sep = "";
-            int profile = configuration.profiles.getProfile(getTypeNameForProfile(classDoc));
-            if (profile > 0) {
-                Content profNameContent = new StringContent();
-                for (int i = profile; i < configuration.profiles.getProfileCount(); i++) {
-                    profNameContent.addContent(sep);
-                    profNameContent.addContent(Profile.lookup(i).name);
-                    sep = ", ";
-                }
-                Content profileNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, profNameContent);
-                div.addContent(profileNameDiv);
-            }
-        }
         if (pkgname.length() > 0) {
-            Content pkgNameContent = new StringContent(pkgname);
-            Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent);
+            Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel);
+            Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
+            pkgNameDiv.addContent(getSpace());
+            Content pkgNameContent = getTargetPackageLink(classDoc.containingPackage(),
+                    "classFrame", new StringContent(pkgname));
+            pkgNameDiv.addContent(pkgNameContent);
             div.addContent(pkgNameDiv);
         }
         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
index b4e3440..5751a70 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -29,6 +29,8 @@
 import java.util.*;
 
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardLocation;
 
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.formats.html.markup.*;
@@ -641,6 +643,12 @@
         return new ContentBuilder();
     }
 
+    @Override
+    public Location getLocationForPackage(PackageDoc pd) {
+        JavaFileManager fm = getFileManager();
+        return StandardLocation.SOURCE_PATH;
+    }
+
     protected void buildSearchTagIndex() {
         for (SearchIndexItem sii : tagSearchIndex) {
             String tagLabel = sii.getLabel();
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
index 4f0ce43..edae147 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, 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
@@ -29,7 +29,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.builders.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -238,6 +237,7 @@
             } catch (IOException e) {
                 throw new DocletAbortException(e);
             } catch (DocletAbortException de) {
+                de.printStackTrace();
                 throw de;
             } catch (Exception e) {
                 e.printStackTrace();
@@ -246,51 +246,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    protected void generateProfileFiles() throws Exception {
-        if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
-            ProfileIndexFrameWriter.generate(configuration);
-            Profile prevProfile = null, nextProfile;
-            String profileName;
-            for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
-                profileName = Profile.lookup(i).name;
-                // Generate profile package pages only if there are any packages
-                // in a profile to be documented. The profilePackages map will not
-                // contain an entry for the profile if there are no packages to be documented.
-                if (!configuration.shouldDocumentProfile(profileName))
-                    continue;
-                ProfilePackageIndexFrameWriter.generate(configuration, profileName);
-                List<PackageDoc> packages = configuration.profilePackages.get(
-                        profileName);
-                PackageDoc prev = null, next;
-                for (int j = 0; j < packages.size(); j++) {
-                    // if -nodeprecated option is set and the package is marked as
-                    // deprecated, do not generate the profilename-package-summary.html
-                    // and profilename-package-frame.html pages for that package.
-                    PackageDoc pkg = packages.get(j);
-                    if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
-                        ProfilePackageFrameWriter.generate(configuration, pkg, i);
-                        next = getNamedPackage(packages, j + 1);
-                        AbstractBuilder profilePackageSummaryBuilder =
-                                configuration.getBuilderFactory().getProfilePackageSummaryBuilder(
-                                pkg, prev, next, Profile.lookup(i));
-                        profilePackageSummaryBuilder.build();
-                        prev = pkg;
-                    }
-                }
-                nextProfile = (i + 1 < configuration.profiles.getProfileCount()) ?
-                        Profile.lookup(i + 1) : null;
-                AbstractBuilder profileSummaryBuilder =
-                        configuration.getBuilderFactory().getProfileSummaryBuilder(
-                        Profile.lookup(i), prevProfile, nextProfile);
-                profileSummaryBuilder.build();
-                prevProfile = Profile.lookup(i);
-            }
-        }
-    }
-
     PackageDoc getNamedPackage(List<PackageDoc> list, int idx) {
         if (idx < list.size()) {
             PackageDoc pkg = list.get(idx);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java
index 63a64a0..e2a6046 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -287,106 +287,6 @@
     }
 
     /**
-     * Get Profile Package link, with target frame.
-     *
-     * @param pd the packageDoc object
-     * @param target name of the target frame
-     * @param label tag for the link
-     * @param profileName the name of the profile being documented
-     * @return a content for the target profile packages link
-     */
-    public Content getTargetProfilePackageLink(PackageDoc pd, String target,
-            Content label, String profileName) {
-        return getHyperLink(pathString(pd, DocPaths.profilePackageSummary(profileName)),
-                label, "", target);
-    }
-
-    /**
-     * Get Profile link, with target frame.
-     *
-     * @param target name of the target frame
-     * @param label tag for the link
-     * @param profileName the name of the profile being documented
-     * @return a content for the target profile link
-     */
-    public Content getTargetProfileLink(String target, Content label,
-            String profileName) {
-        return getHyperLink(pathToRoot.resolve(
-                DocPaths.profileSummary(profileName)), label, "", target);
-    }
-
-    /**
-     * Get the type name for profile search.
-     *
-     * @param cd the classDoc object for which the type name conversion is needed
-     * @return a type name string for the type
-     */
-    public String getTypeNameForProfile(ClassDoc cd) {
-        StringBuilder typeName =
-                new StringBuilder((cd.containingPackage()).name().replace(".", "/"));
-        typeName.append("/")
-                .append(cd.name().replace(".", "$"));
-        return typeName.toString();
-    }
-
-    /**
-     * Check if a type belongs to a profile.
-     *
-     * @param cd the classDoc object that needs to be checked
-     * @param profileValue the profile in which the type needs to be checked
-     * @return true if the type is in the profile
-     */
-    public boolean isTypeInProfile(ClassDoc cd, int profileValue) {
-        return (configuration.profiles.getProfile(getTypeNameForProfile(cd)) <= profileValue);
-    }
-
-    public void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content summaryContentTree,
-            int profileValue) {
-        if(classes.length > 0) {
-            Arrays.sort(classes);
-            Content caption = getTableCaption(new RawHtml(label));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption);
-            table.addContent(getSummaryTableHeader(tableHeader, "col"));
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            for (int i = 0; i < classes.length; i++) {
-                if (!isTypeInProfile(classes[i], profileValue)) {
-                    continue;
-                }
-                if (!utils.isCoreClass(classes[i]) ||
-                    !configuration.isGeneratedDoc(classes[i])) {
-                    continue;
-                }
-                Content classContent = getLink(new LinkInfoImpl(
-                        configuration, LinkInfoImpl.Kind.PACKAGE, classes[i]));
-                Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent);
-                HtmlTree tr = HtmlTree.TR(tdClass);
-                if (i%2 == 0)
-                    tr.addStyle(HtmlStyle.altColor);
-                else
-                    tr.addStyle(HtmlStyle.rowColor);
-                HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
-                tdClassDescription.addStyle(HtmlStyle.colLast);
-                if (utils.isDeprecated(classes[i])) {
-                    tdClassDescription.addContent(deprecatedLabel);
-                    if (classes[i].tags("deprecated").length > 0) {
-                        addSummaryDeprecatedComment(classes[i],
-                            classes[i].tags("deprecated")[0], tdClassDescription);
-                    }
-                }
-                else
-                    addSummaryComment(classes[i], tdClassDescription);
-                tr.addContent(tdClassDescription);
-                tbody.addContent(tr);
-            }
-            table.addContent(tbody);
-            summaryContentTree.addContent(table);
-        }
-    }
-
-    /**
      * Generates the HTML document tree and prints it out.
      *
      * @param metakeywords Array of String keywords for META tag. Each element
@@ -593,6 +493,8 @@
                 fixedNavDiv.addContent(subDiv);
                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
                 tree.addContent(fixedNavDiv);
+                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, getSpace());
+                tree.addContent(paddingDiv);
             } else {
                 subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
                 tree.addContent(subDiv);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java
index e24d25f..10b0a8b 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -158,19 +158,6 @@
     }
 
     /**
-     * Adds "All Profiles" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the "All Profiles" link should be added
-     */
-    protected void addAllProfilesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.PROFILE_OVERVIEW_FRAME,
-                allprofilesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
      * {@inheritDoc}
      */
     protected void addNavigationBarFooter(Content body) {
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java
index 93070da..6cf48e4 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java
@@ -29,7 +29,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.formats.html.markup.*;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -127,34 +126,6 @@
     /**
      * {@inheritDoc}
      */
-    protected void addProfilesList(Content profileSummary, Content body) {
-        Content h2 = HtmlTree.HEADING(HtmlTag.H2, profileSummary);
-        Content profilesDiv = HtmlTree.DIV(h2);
-        Content ul = new HtmlTree(HtmlTag.UL);
-        String profileName;
-        for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
-            profileName = Profile.lookup(i).name;
-            // If the profile has valid packages to be documented, add it to the
-            // profiles list on overview-summary.html page.
-            if (configuration.shouldDocumentProfile(profileName)) {
-                Content profileLinkContent = getTargetProfileLink("classFrame",
-                        new StringContent(profileName), profileName);
-                Content li = HtmlTree.LI(profileLinkContent);
-                ul.addContent(li);
-            }
-        }
-        profilesDiv.addContent(ul);
-        Content div = HtmlTree.DIV(HtmlStyle.contentContainer, profilesDiv);
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            htmlTree.addContent(div);
-        } else {
-            body.addContent(div);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     protected void addPackagesList(Collection<PackageDoc> packages, String text,
             String tableSummary, Content body) {
         Content table = (configuration.isOutputHtml5())
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java
deleted file mode 100644
index cbe23cf..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-import java.util.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Class to generate file for each package contents of a profile in the left-hand bottom
- * frame. This will list all the Class Kinds in the package for a profile. A click on any
- * class-kind will update the right-hand frame with the clicked class-kind page.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageFrameWriter extends HtmlDocletWriter {
-
-    /**
-     * The package being documented.
-     */
-    private PackageDoc packageDoc;
-
-    /**
-     * Constructor to construct ProfilePackageFrameWriter object and to generate
-     * "profilename-package-frame.html" file in the respective package directory.
-     * For example for profile compact1 and package "java.lang" this will generate file
-     * "compact1-package-frame.html" file in the "java/lang" directory. It will also
-     * create "java/lang" directory in the current or the destination directory
-     * if it doesn't exist.
-     *
-     * @param configuration the configuration of the doclet.
-     * @param packageDoc PackageDoc under consideration.
-     * @param profileName the name of the profile being documented
-     */
-    public ProfilePackageFrameWriter(ConfigurationImpl configuration,
-            PackageDoc packageDoc, String profileName)
-            throws IOException {
-        super(configuration, DocPath.forPackage(packageDoc).resolve(
-                DocPaths.profilePackageFrame(profileName)));
-        this.packageDoc = packageDoc;
-    }
-
-    /**
-     * Generate a profile package summary page for the left-hand bottom frame. Construct
-     * the ProfilePackageFrameWriter object and then uses it generate the file.
-     *
-     * @param configuration the current configuration of the doclet.
-     * @param packageDoc The package for which "profilename-package-frame.html" is to be generated.
-     * @param profileValue the value of the profile being documented
-     */
-    public static void generate(ConfigurationImpl configuration,
-            PackageDoc packageDoc, int profileValue) {
-        ProfilePackageFrameWriter profpackgen;
-        try {
-            String profileName = Profile.lookup(profileValue).name;
-            profpackgen = new ProfilePackageFrameWriter(configuration, packageDoc,
-                    profileName);
-            StringBuilder winTitle = new StringBuilder(profileName);
-            String sep = " - ";
-            winTitle.append(sep);
-            String pkgName = configuration.utils.getPackageName(packageDoc);
-            winTitle.append(pkgName);
-            HtmlTree body = profpackgen.getBody(false,
-                    profpackgen.getWindowTitle(winTitle.toString()));
-            Content profName = new StringContent(profileName);
-            Content sepContent = new StringContent(sep);
-            Content pkgNameContent = new RawHtml(pkgName);
-            HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
-                    ? HtmlTree.MAIN()
-                    : body;
-            Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, HtmlStyle.bar,
-                    profpackgen.getTargetProfileLink("classFrame", profName, profileName));
-            heading.addContent(sepContent);
-            heading.addContent(profpackgen.getTargetProfilePackageLink(packageDoc,
-                    "classFrame", pkgNameContent, profileName));
-            htmlTree.addContent(heading);
-            HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.addStyle(HtmlStyle.indexContainer);
-            profpackgen.addClassListing(div, profileValue);
-            htmlTree.addContent(div);
-            if (configuration.allowTag(HtmlTag.MAIN)) {
-                body.addContent(htmlTree);
-            }
-            profpackgen.printHtmlDocument(
-                    configuration.metakeywords.getMetaKeywords(packageDoc), false, body);
-            profpackgen.close();
-        } catch (IOException exc) {
-            configuration.standardmessage.error(
-                    "doclet.exception_encountered",
-                    exc.toString(), DocPaths.PACKAGE_FRAME.getPath());
-            throw new DocletAbortException(exc);
-        }
-    }
-
-    /**
-     * Add class listing for all the classes in this package. Divide class
-     * listing as per the class kind and generate separate listing for
-     * Classes, Interfaces, Exceptions and Errors.
-     *
-     * @param contentTree the content tree to which the listing will be added
-     * @param profileValue the value of the profile being documented
-     */
-    protected void addClassListing(HtmlTree contentTree, int profileValue) {
-        if (packageDoc.isIncluded()) {
-            addClassKindListing(packageDoc.interfaces(),
-                getResource("doclet.Interfaces"), contentTree, profileValue);
-            addClassKindListing(packageDoc.ordinaryClasses(),
-                getResource("doclet.Classes"), contentTree, profileValue);
-            addClassKindListing(packageDoc.enums(),
-                getResource("doclet.Enums"), contentTree, profileValue);
-            addClassKindListing(packageDoc.exceptions(),
-                getResource("doclet.Exceptions"), contentTree, profileValue);
-            addClassKindListing(packageDoc.errors(),
-                getResource("doclet.Errors"), contentTree, profileValue);
-            addClassKindListing(packageDoc.annotationTypes(),
-                getResource("doclet.AnnotationTypes"), contentTree, profileValue);
-        }
-    }
-
-    /**
-     * Add specific class kind listing. Also add label to the listing.
-     *
-     * @param arr Array of specific class kinds, namely Class or Interface or Exception or Error
-     * @param labelContent content tree of the label to be added
-     * @param contentTree the content tree to which the class kind listing will be added
-     * @param profileValue the value of the profile being documented
-     */
-    protected void addClassKindListing(ClassDoc[] arr, Content labelContent,
-            HtmlTree contentTree, int profileValue) {
-        if(arr.length > 0) {
-            Arrays.sort(arr);
-            boolean printedHeader = false;
-            HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
-                    ? HtmlTree.SECTION()
-                    : contentTree;
-            HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            ul.setTitle(labelContent);
-            for (ClassDoc classDoc : arr) {
-                if (!isTypeInProfile(classDoc, profileValue)) {
-                    continue;
-                }
-                if (!utils.isCoreClass(classDoc) || !
-                        configuration.isGeneratedDoc(classDoc)) {
-                    continue;
-                }
-                if (!printedHeader) {
-                    Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
-                                                       true, labelContent);
-                    htmlTree.addContent(heading);
-                    printedHeader = true;
-                }
-                Content arr_i_name = new StringContent(classDoc.name());
-                if (classDoc.isInterface())
-                    arr_i_name = HtmlTree.SPAN(HtmlStyle.interfaceName, arr_i_name);
-                Content link = getLink(new LinkInfoImpl(configuration,
-                                                        LinkInfoImpl.Kind.PACKAGE_FRAME, classDoc).label(arr_i_name).target("classFrame"));
-                Content li = HtmlTree.LI(link);
-                ul.addContent(li);
-            }
-            htmlTree.addContent(ul);
-            if (configuration.allowTag(HtmlTag.SECTION)) {
-                contentTree.addContent(htmlTree);
-            }
-        }
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java
deleted file mode 100644
index 9a705d5..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.IOException;
-import java.util.List;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Generate the profile package index for the left-hand frame in the generated output.
- * A click on the package name in this frame will update the page in the bottom
- * left hand frame with the listing of contents of the clicked profile package.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageIndexFrameWriter extends AbstractProfileIndexWriter {
-
-    /**
-     * Construct the ProfilePackageIndexFrameWriter object.
-     *
-     * @param configuration the configuration object
-     * @param filename Name of the package index file to be generated.
-     */
-    public ProfilePackageIndexFrameWriter(ConfigurationImpl configuration,
-                                   DocPath filename) throws IOException {
-        super(configuration, filename);
-    }
-
-    /**
-     * Generate the profile package index file.
-     * @throws DocletAbortException
-     * @param configuration the configuration object
-     * @param profileName the name of the profile being documented
-     */
-    public static void generate(ConfigurationImpl configuration, String profileName) {
-        ProfilePackageIndexFrameWriter profpackgen;
-        DocPath filename = DocPaths.profileFrame(profileName);
-        try {
-            profpackgen = new ProfilePackageIndexFrameWriter(configuration, filename);
-            profpackgen.buildProfilePackagesIndexFile("doclet.Window_Overview", false, profileName);
-            profpackgen.close();
-        } catch (IOException exc) {
-            configuration.standardmessage.error(
-                        "doclet.exception_encountered",
-                        exc.toString(), filename);
-            throw new DocletAbortException(exc);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addProfilePackagesList(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName) {
-        Content profNameContent = new StringContent(profileName);
-        Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true,
-                getTargetProfileLink("classFrame", profNameContent, profileName));
-        heading.addContent(getSpace());
-        heading.addContent(packagesLabel);
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
-                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
-                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.setTitle(packagesLabel);
-        List<PackageDoc> packages = configuration.profilePackages.get(profileName);
-        for (PackageDoc packageDoc : packages) {
-            if ((!(configuration.nodeprecated && utils.isDeprecated(packageDoc)))) {
-                ul.addContent(getPackage(packageDoc, profileName));
-            }
-        }
-        htmlTree.addContent(ul);
-        body.addContent(htmlTree);
-    }
-
-    /**
-     * Returns each package name as a separate link.
-     *
-     * @param pd PackageDoc
-     * @param profileName the name of the profile being documented
-     * @return content for the package link
-     */
-    protected Content getPackage(PackageDoc pd, String profileName) {
-        Content packageLinkContent;
-        Content pkgLabel;
-        if (pd.name().length() > 0) {
-            pkgLabel = getPackageLabel(pd.name());
-            packageLinkContent = getHyperLink(pathString(pd,
-                     DocPaths.profilePackageFrame(profileName)), pkgLabel, "",
-                    "packageFrame");
-        } else {
-            pkgLabel = new StringContent("<unnamed package>");
-            packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME,
-                    pkgLabel, "", "packageFrame");
-        }
-        Content li = HtmlTree.LI(packageLinkContent);
-        return li;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addNavigationBarHeader(Content body) {
-        Content headerContent;
-        if (configuration.packagesheader.length() > 0) {
-            headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader));
-        } else {
-            headerContent = new RawHtml(replaceDocRootDir(configuration.header));
-        }
-        Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.bar, headerContent);
-        body.addContent(heading);
-    }
-
-    /**
-     * Do nothing as there is no overview information in this page.
-     */
-    protected void addOverviewHeader(Content body) {
-    }
-
-    protected void addProfilesList(Profiles profiles, String text,
-            String tableSummary, Content body) {
-    }
-
-    /**
-     * Adds "All Classes" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all classes link should be added
-     */
-    protected void addAllClassesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
-                allclassesLabel, "", "packageFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * Adds "All Packages" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all packages link should be added
-     */
-    protected void addAllPackagesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
-                allpackagesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * Adds "All Profiles" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all profiles link should be added
-     */
-    protected void addAllProfilesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.PROFILE_OVERVIEW_FRAME,
-                allprofilesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addNavigationBarFooter(Content body) {
-        Content p = HtmlTree.P(getSpace());
-        body.addContent(p);
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java
deleted file mode 100644
index 903bcf9..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Class to generate file for each profile package contents in the right-hand
- * frame. This will list all the Class Kinds in the package. A click on any
- * class-kind will update the frame with the clicked class-kind page.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageWriterImpl extends HtmlDocletWriter
-    implements ProfilePackageSummaryWriter {
-
-    /**
-     * The prev package name in the alpha-order list.
-     */
-    protected PackageDoc prev;
-
-    /**
-     * The next package name in the alpha-order list.
-     */
-    protected PackageDoc next;
-
-    /**
-     * The profile package being documented.
-     */
-    protected PackageDoc packageDoc;
-
-    /**
-     * The name of the profile being documented.
-     */
-    protected String profileName;
-
-    /**
-     * The value of the profile being documented.
-     */
-    protected int profileValue;
-
-    /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
-     * The HTML tree for section tag.
-     */
-    protected HtmlTree sectionTree = HtmlTree.SECTION();
-
-    /**
-     * Constructor to construct ProfilePackageWriter object and to generate
-     * "profilename-package-summary.html" file in the respective package directory.
-     * For example for profile compact1 and package "java.lang" this will generate file
-     * "compact1-package-summary.html" file in the "java/lang" directory. It will also
-     * create "java/lang" directory in the current or the destination directory
-     * if it doesn't exist.
-     *
-     * @param configuration the configuration of the doclet.
-     * @param packageDoc    PackageDoc under consideration.
-     * @param prev          Previous package in the sorted array.
-     * @param next          Next package in the sorted array.
-     * @param profile       The profile being documented.
-     */
-    public ProfilePackageWriterImpl(ConfigurationImpl configuration,
-            PackageDoc packageDoc, PackageDoc prev, PackageDoc next,
-            Profile profile) throws IOException {
-        super(configuration, DocPath.forPackage(packageDoc).resolve(
-                DocPaths.profilePackageSummary(profile.name)));
-        this.prev = prev;
-        this.next = next;
-        this.packageDoc = packageDoc;
-        this.profileName = profile.name;
-        this.profileValue = profile.value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getPackageHeader(String heading) {
-        HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getPackageName(packageDoc)));
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
-                ? HtmlTree.HEADER()
-                : bodyTree;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
-        if (configuration.allowTag(HtmlTag.HEADER)) {
-            bodyTree.addContent(htmlTree);
-        }
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
-        Content profileContent = new StringContent(profileName);
-        Content profileNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, profileContent);
-        div.addContent(profileNameDiv);
-        Content annotationContent = new HtmlTree(HtmlTag.P);
-        addAnnotationInfo(packageDoc, annotationContent);
-        div.addContent(annotationContent);
-        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.title, packageLabel);
-        tHeading.addContent(getSpace());
-        Content packageHead = new RawHtml(heading);
-        tHeading.addContent(packageHead);
-        div.addContent(tHeading);
-        addDeprecationInfo(div);
-        if (packageDoc.inlineTags().length > 0 && ! configuration.nocomment) {
-            HtmlTree docSummaryDiv = new HtmlTree(HtmlTag.DIV);
-            docSummaryDiv.addStyle(HtmlStyle.docSummary);
-            addSummaryComment(packageDoc, docSummaryDiv);
-            div.addContent(docSummaryDiv);
-            Content space = getSpace();
-            Content descLink = getHyperLink(getDocLink(
-                    SectionName.PACKAGE_DESCRIPTION),
-                    descriptionLabel, "", "");
-            Content descPara = new HtmlTree(HtmlTag.P, seeLabel, space, descLink);
-            div.addContent(descPara);
-        }
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            mainTree.addContent(div);
-        } else {
-            bodyTree.addContent(div);
-        }
-        return bodyTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getContentHeader() {
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
-        return div;
-    }
-
-    /**
-     * Add the package deprecation information to the documentation tree.
-     *
-     * @param div the content tree to which the deprecation information will be added
-     */
-    public void addDeprecationInfo(Content div) {
-        Tag[] deprs = packageDoc.tags("deprecated");
-        if (utils.isDeprecated(packageDoc)) {
-            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecatedContent);
-            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
-            deprDiv.addContent(deprPhrase);
-            if (deprs.length > 0) {
-                Tag[] commentTags = deprs[0].inlineTags();
-                if (commentTags.length > 0) {
-                    addInlineDeprecatedComment(packageDoc, deprs[0], deprDiv);
-                }
-            }
-            div.addContent(deprDiv);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content packageSummaryContentTree) {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
-        addClassesSummary(classes, label, tableSummary, tableHeader,
-                li, profileValue);
-        packageSummaryContentTree.addContent(li);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getSummaryHeader() {
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
-        return ul;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageDescription(Content packageContentTree) {
-        if (packageDoc.inlineTags().length > 0) {
-            packageContentTree.addContent(
-                    getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION));
-            Content h2Content = new StringContent(
-                    configuration.getText("doclet.Package_Description",
-                    packageDoc.name()));
-            Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, h2Content);
-            if (configuration.allowTag(HtmlTag.SECTION)) {
-                sectionTree.addContent(heading);
-                addInlineComment(packageDoc, sectionTree);
-            } else {
-                packageContentTree.addContent(heading);
-                addInlineComment(packageDoc, packageContentTree);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageTags(Content packageContentTree) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.SECTION))
-                ? sectionTree
-                : packageContentTree;
-        addTagsInfo(packageDoc, htmlTree);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageContent(Content contentTree, Content packageContentTree) {
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            packageContentTree.addContent(sectionTree);
-            mainTree.addContent(packageContentTree);
-            contentTree.addContent(mainTree);
-        } else {
-            contentTree.addContent(packageContentTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageFooter(Content contentTree) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
-                ? HtmlTree.FOOTER()
-                : contentTree;
-        addNavLinks(false, htmlTree);
-        addBottom(htmlTree);
-        if (configuration.allowTag(HtmlTag.FOOTER)) {
-            contentTree.addContent(htmlTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void printDocument(Content contentTree) throws IOException {
-        printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageDoc),
-                true, contentTree);
-    }
-
-    /**
-     * Get "Use" link for this package in the navigation bar.
-     *
-     * @return a content tree for the class use link
-     */
-    protected Content getNavLinkClassUse() {
-        Content useLink = getHyperLink(DocPaths.PACKAGE_USE,
-                useLabel, "", "");
-        Content li = HtmlTree.LI(useLink);
-        return li;
-    }
-
-    /**
-     * Get "PREV PACKAGE" link in the navigation bar.
-     *
-     * @return a content tree for the previous link
-     */
-    public Content getNavLinkPrevious() {
-        Content li;
-        if (prev == null) {
-            li = HtmlTree.LI(prevpackageLabel);
-        } else {
-            DocPath path = DocPath.relativePath(packageDoc, prev);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.profilePackageSummary(profileName)),
-                prevpackageLabel, "", ""));
-        }
-        return li;
-    }
-
-    /**
-     * Get "NEXT PACKAGE" link in the navigation bar.
-     *
-     * @return a content tree for the next link
-     */
-    public Content getNavLinkNext() {
-        Content li;
-        if (next == null) {
-            li = HtmlTree.LI(nextpackageLabel);
-        } else {
-            DocPath path = DocPath.relativePath(packageDoc, next);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.profilePackageSummary(profileName)),
-                nextpackageLabel, "", ""));
-        }
-        return li;
-    }
-
-    /**
-     * Get "Tree" link in the navigation bar. This will be link to the package
-     * tree file.
-     *
-     * @return a content tree for the tree link
-     */
-    protected Content getNavLinkTree() {
-        Content useLink = getHyperLink(DocPaths.PACKAGE_TREE,
-                treeLabel, "", "");
-        Content li = HtmlTree.LI(useLink);
-        return li;
-    }
-
-    /**
-     * Highlight "Package" in the navigation bar, as this is the package page.
-     *
-     * @return a content tree for the package link
-     */
-    protected Content getNavLinkPackage() {
-        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, packageLabel);
-        return li;
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java
deleted file mode 100644
index a86dfa1..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Class to generate file for each profile contents in the right-hand
- * frame. This will list all the packages and Class Kinds in the profile. A click on any
- * class-kind will update the frame with the clicked class-kind page. A click on any
- * package will update the frame with the clicked profile package page.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfileWriterImpl extends HtmlDocletWriter
-    implements ProfileSummaryWriter {
-
-    /**
-     * The prev profile name in the alpha-order list.
-     */
-    protected Profile prevProfile;
-
-    /**
-     * The next profile name in the alpha-order list.
-     */
-    protected Profile nextProfile;
-
-    /**
-     * The profile being documented.
-     */
-    protected Profile profile;
-
-    /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
-     * Constructor to construct ProfileWriter object and to generate
-     * "profileName-summary.html" file.
-     *
-     * @param configuration the configuration of the doclet.
-     * @param profile       Profile under consideration.
-     * @param prevProfile   Previous profile in the sorted array.
-     * @param nextProfile   Next profile in the sorted array.
-     */
-    public ProfileWriterImpl(ConfigurationImpl configuration,
-            Profile profile, Profile prevProfile, Profile nextProfile)
-            throws IOException {
-        super(configuration, DocPaths.profileSummary(profile.name));
-        this.prevProfile = prevProfile;
-        this.nextProfile = nextProfile;
-        this.profile = profile;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getProfileHeader(String heading) {
-        String profileName = profile.name;
-        HtmlTree bodyTree = getBody(true, getWindowTitle(profileName));
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
-                ? HtmlTree.HEADER()
-                : bodyTree;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
-        if (configuration.allowTag(HtmlTag.HEADER)) {
-            bodyTree.addContent(htmlTree);
-        }
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
-        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.title, profileLabel);
-        tHeading.addContent(getSpace());
-        Content profileHead = new RawHtml(heading);
-        tHeading.addContent(profileHead);
-        div.addContent(tHeading);
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            mainTree.addContent(div);
-        } else {
-            bodyTree.addContent(div);
-        }
-        return bodyTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getContentHeader() {
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
-        return div;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getSummaryHeader() {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
-        return li;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getSummaryTree(Content summaryContentTree) {
-        HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
-        HtmlTree div = HtmlTree.DIV(HtmlStyle.summary, ul);
-        return div;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getPackageSummaryHeader(PackageDoc pkg) {
-        Content pkgName = new StringContent(pkg.name());
-        Content pkgNameLink = getTargetProfilePackageLink(pkg,
-                    "classFrame", pkgName, profile.name);
-        Content heading = HtmlTree.HEADING(HtmlTag.H3, pkgNameLink);
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
-                ? HtmlTree.SECTION(heading)
-                : HtmlTree.LI(HtmlStyle.blockList, heading);
-        addPackageDeprecationInfo(htmlTree, pkg);
-        return htmlTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getPackageSummaryTree(Content packageSummaryContentTree) {
-        HtmlTree htmlTree;
-        if (configuration.allowTag(HtmlTag.SECTION)) {
-            htmlTree = HtmlTree.UL(HtmlStyle.blockList,
-                    HtmlTree.LI(HtmlStyle.blockList, packageSummaryContentTree));
-        } else {
-            htmlTree = HtmlTree.UL(HtmlStyle.blockList, packageSummaryContentTree);
-        }
-        return htmlTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content packageSummaryContentTree) {
-        addClassesSummary(classes, label, tableSummary, tableHeader,
-                packageSummaryContentTree, profile.value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addProfileContent(Content contentTree, Content profileContentTree) {
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            mainTree.addContent(profileContentTree);
-            contentTree.addContent(mainTree);
-        } else {
-            contentTree.addContent(profileContentTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addProfileFooter(Content contentTree) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
-                ? HtmlTree.FOOTER()
-                : contentTree;
-        addNavLinks(false, htmlTree);
-        addBottom(htmlTree);
-        if (configuration.allowTag(HtmlTag.FOOTER)) {
-            contentTree.addContent(htmlTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void printDocument(Content contentTree) throws IOException {
-        printHtmlDocument(configuration.metakeywords.getMetaKeywords(profile),
-                true, contentTree);
-    }
-
-    /**
-     * Add the profile package deprecation information to the documentation tree.
-     *
-     * @param li the content tree to which the deprecation information will be added
-     * @param pkg the PackageDoc that is added
-     */
-    public void addPackageDeprecationInfo(Content li, PackageDoc pkg) {
-        Tag[] deprs;
-        if (utils.isDeprecated(pkg)) {
-            deprs = pkg.tags("deprecated");
-            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecatedContent);
-            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
-            deprDiv.addContent(deprPhrase);
-            if (deprs.length > 0) {
-                Tag[] commentTags = deprs[0].inlineTags();
-                if (commentTags.length > 0) {
-                    addInlineDeprecatedComment(pkg, deprs[0], deprDiv);
-                }
-            }
-            li.addContent(deprDiv);
-        }
-    }
-
-    /**
-     * Get "PREV PROFILE" link in the navigation bar.
-     *
-     * @return a content tree for the previous link
-     */
-    public Content getNavLinkPrevious() {
-        Content li;
-        if (prevProfile == null) {
-            li = HtmlTree.LI(prevprofileLabel);
-        } else {
-            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.profileSummary(
-                    prevProfile.name)), prevprofileLabel, "", ""));
-        }
-        return li;
-    }
-
-    /**
-     * Get "NEXT PROFILE" link in the navigation bar.
-     *
-     * @return a content tree for the next link
-     */
-    public Content getNavLinkNext() {
-        Content li;
-        if (nextProfile == null) {
-            li = HtmlTree.LI(nextprofileLabel);
-        } else {
-            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.profileSummary(
-                    nextProfile.name)), nextprofileLabel, "", ""));
-        }
-        return li;
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java
index 70bace9..f2401ac 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -28,7 +28,6 @@
 import java.io.IOException;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
@@ -70,24 +69,6 @@
     /**
      * {@inheritDoc}
      */
-    public ProfileSummaryWriter getProfileSummaryWriter(Profile profile,
-        Profile prevProfile, Profile nextProfile) throws Exception {
-        return new ProfileWriterImpl(configuration, profile,
-            prevProfile, nextProfile);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ProfilePackageSummaryWriter getProfilePackageSummaryWriter(PackageDoc packageDoc,
-        PackageDoc prevPkg, PackageDoc nextPkg, Profile profile) throws Exception {
-        return new ProfilePackageWriterImpl(configuration, packageDoc,
-            prevPkg, nextPkg, profile);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public ClassWriter getClassWriter(ClassDoc classDoc, ClassDoc prevClass,
             ClassDoc nextClass, ClassTree classTree) throws IOException {
         return new ClassWriterImpl(configuration, classDoc,
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java
index aa18de7..e5addad 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -192,11 +192,6 @@
     public static final HtmlTag PACKAGE_HEADING = HtmlTag.H2;
 
     /**
-     * Html tag for the profile name heading.
-     */
-    public static final HtmlTag PROFILE_HEADING = HtmlTag.H2;
-
-    /**
      * Html tag for the member summary heading.
      */
     public static final HtmlTag SUMMARY_HEADING = HtmlTag.H3;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java
index 75f291b..0d472eb 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -81,9 +81,11 @@
     navBarCell1Rev,
     navList,
     navListSearch,
+    navPadding,
     overrideSpecifyLabel,
     overviewSummary,
     packageHierarchyLabel,
+    packageLabelInClass,
     paramLabel,
     returnLabel,
     rightContainer,
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
index 2107273..19940dc 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
@@ -27,8 +27,6 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -65,11 +63,6 @@
     protected boolean memberDetailsListPrinted;
 
     /**
-     * Header for table displaying profiles and description..
-     */
-    protected final String[] profileTableHeader;
-
-    /**
      * Header for tables displaying packages and description..
      */
     protected final String[] packageTableHeader;
@@ -90,8 +83,6 @@
 
     public final Content packageLabel;
 
-    public final Content profileLabel;
-
     public final Content useLabel;
 
     public final Content prevLabel;
@@ -122,8 +113,6 @@
 
     public final Content allpackagesLabel;
 
-    public final Content allprofilesLabel;
-
     public final Content indexLabel;
 
     public final Content helpLabel;
@@ -136,14 +125,8 @@
 
     public final Content nextpackageLabel;
 
-    public final Content prevprofileLabel;
-
-    public final Content nextprofileLabel;
-
     public final Content packagesLabel;
 
-    public final Content profilesLabel;
-
     public final Content methodDetailsLabel;
 
     public final Content annotationTypeDetailsLabel;
@@ -183,10 +166,6 @@
         writer = DocFile.createFileForOutput(configuration, path).openWriter();
         this.configuration = configuration;
         this.memberDetailsListPrinted = false;
-        profileTableHeader = new String[] {
-            configuration.getText("doclet.Profile"),
-            configuration.getText("doclet.Description")
-        };
         packageTableHeader = new String[] {
             configuration.getText("doclet.Package"),
             configuration.getText("doclet.Description")
@@ -199,7 +178,6 @@
         overviewLabel = getResource("doclet.Overview");
         defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME);
         packageLabel = getResource("doclet.Package");
-        profileLabel = getResource("doclet.Profile");
         useLabel = getResource("doclet.navClassUse");
         prevLabel = getResource("doclet.Prev");
         nextLabel = getResource("doclet.Next");
@@ -215,17 +193,13 @@
         deprecatedPhrase = getResource("doclet.Deprecated");
         allclassesLabel = getNonBreakResource("doclet.All_Classes");
         allpackagesLabel = getNonBreakResource("doclet.All_Packages");
-        allprofilesLabel = getNonBreakResource("doclet.All_Profiles");
         indexLabel = getResource("doclet.Index");
         helpLabel = getResource("doclet.Help");
         seeLabel = getResource("doclet.See");
         descriptionLabel = getResource("doclet.Description");
         prevpackageLabel = getNonBreakResource("doclet.Prev_Package");
         nextpackageLabel = getNonBreakResource("doclet.Next_Package");
-        prevprofileLabel = getNonBreakResource("doclet.Prev_Profile");
-        nextprofileLabel = getNonBreakResource("doclet.Next_Profile");
         packagesLabel = getResource("doclet.Packages");
-        profilesLabel = getResource("doclet.Profiles");
         methodDetailsLabel = getResource("doclet.Method_Detail");
         annotationTypeDetailsLabel = getResource("doclet.Annotation_Type_Member_Detail");
         fieldDetailsLabel = getResource("doclet.Field_Detail");
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
index e5cadd9..0efe7ee 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
@@ -4,9 +4,7 @@
 doclet.Window_Overview=Overview List
 doclet.Window_Overview_Summary=Overview
 doclet.Package=Package
-doclet.Profile=Profile
 doclet.All_Packages=All Packages
-doclet.All_Profiles=All Profiles
 doclet.Tree=Tree
 doclet.Class_Hierarchy=Class Hierarchy
 doclet.Window_Class_Hierarchy=Class Hierarchy
@@ -19,8 +17,6 @@
 doclet.Next_Class=Next Class
 doclet.Prev_Package=Prev Package
 doclet.Next_Package=Next Package
-doclet.Prev_Profile=Prev Profile
-doclet.Next_Profile=Next Profile
 doclet.Prev_Letter=Prev Letter
 doclet.Next_Letter=Next Letter
 doclet.Href_Class_Title=class in {0}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
index ce4f620..e4d62a1 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
@@ -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
@@ -25,6 +25,8 @@
 
 package com.sun.tools.doclets.internal.toolkit;
 
+import javax.tools.StandardLocation;
+
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.internal.toolkit.builders.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -88,6 +90,7 @@
             root.printError(f.getMessage());
             return false;
         } catch (DocletAbortException e) {
+            e.printStackTrace();
             Throwable cause = e.getCause();
             if (cause != null) {
                 if (cause.getLocalizedMessage() != null) {
@@ -138,11 +141,10 @@
         ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
 
         generateClassFiles(root, classtree);
-        configuration.utils.copyDocFiles(configuration, DocPaths.DOC_FILES);
+        configuration.utils.copyDocFiles(configuration, StandardLocation.SOURCE_PATH, DocPaths.DOC_FILES);
 
         PackageListWriter.generate(configuration);
         generatePackageFiles(classtree);
-        generateProfileFiles();
 
         generateOtherFiles(root, classtree);
         configuration.tagletManager.printReport();
@@ -163,12 +165,6 @@
     }
 
     /**
-     * Generate the profile documentation.
-     *
-     */
-    protected abstract void generateProfileFiles() throws Exception;
-
-    /**
      * Generate the package documentation.
      *
      * @param classtree the data structure representing the class tree.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
index 85dcb07..f86f874 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
@@ -31,14 +31,12 @@
 import java.util.regex.Pattern;
 
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
-import com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap.GetterSetter;
 import com.sun.tools.javac.util.StringUtils;
 
 /**
@@ -212,16 +210,6 @@
      * used.Default is don't show version information.
      */
     public boolean showversion = false;
-    /**
-     * Argument for command line option "-Xprofilespath".
-     */
-    public String profilespath = "";
-
-    /**
-     * Generate profiles documentation if profilespath is set and valid profiles
-     * are present.
-     */
-    public boolean showProfiles = false;
 
     /**
      * Don't generate deprecated API information at all, if -nodeprecated
@@ -283,28 +271,13 @@
     public abstract MessageRetriever getDocletSpecificMsg();
 
     /**
-     * A profiles object used to access profiles across various pages.
-     */
-    public Profiles profiles;
-
-    /**
-     * A map of the profiles to packages.
-     */
-    public Map<String, List<PackageDoc>> profilePackages;
-
-    /**
      * A sorted set of packages specified on the command-line merged with a
      * collection of packages that contain the classes specified on the
      * command-line.
      */
     public SortedSet<PackageDoc> packages;
 
-    // The following three fields provide caches for use by all instances of VisibleMemberMap.
-    public final Map<ClassDoc, ProgramElementDoc[]> propertiesCache = new HashMap<>();
-    public final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap = new HashMap<>();
-    public final Map<ProgramElementDoc, GetterSetter> getterSetterMap = new HashMap<>();
-
-    public DocFileFactory docFileFactory;
+    public boolean exportInternalAPI;
 
     /**
      * Constructor. Constructs the message retriever with resource file.
@@ -360,6 +333,7 @@
             case "-quiet":
             case "-xnodate":
             case "-version":
+            case "-xdaccessinternalapi":
                 return 1;
             case "-d":
             case "-docencoding":
@@ -373,7 +347,6 @@
             case "-tag":
             case "-taglet":
             case "-tagletpath":
-            case "-xprofilespath":
                 return 2;
             case "-group":
             case "-linkoffline":
@@ -392,54 +365,6 @@
     public abstract boolean validOptions(String options[][],
         DocErrorReporter reporter);
 
-    private void initProfiles() throws IOException {
-        if (profilespath.isEmpty())
-            return;
-
-        profiles = Profiles.read(new File(profilespath));
-
-        // Group the packages to be documented by the lowest profile (if any)
-        // in which each appears
-        Map<Profile, List<PackageDoc>> interimResults = new EnumMap<>(Profile.class);
-        for (Profile p: Profile.values())
-            interimResults.put(p, new ArrayList<PackageDoc>());
-
-        for (PackageDoc pkg: packages) {
-            if (nodeprecated && utils.isDeprecated(pkg)) {
-                continue;
-            }
-            // the getProfile method takes a type name, not a package name,
-            // but isn't particularly fussy about the simple name -- so just use *
-            int i = profiles.getProfile(pkg.name().replace(".", "/") + "/*");
-            Profile p = Profile.lookup(i);
-            if (p != null) {
-                List<PackageDoc> pkgs = interimResults.get(p);
-                pkgs.add(pkg);
-            }
-        }
-
-        // Build the profilePackages structure used by the doclet
-        profilePackages = new HashMap<>();
-        List<PackageDoc> prev = Collections.<PackageDoc>emptyList();
-        int size;
-        for (Map.Entry<Profile,List<PackageDoc>> e: interimResults.entrySet()) {
-            Profile p = e.getKey();
-            List<PackageDoc> pkgs =  e.getValue();
-            pkgs.addAll(prev); // each profile contains all lower profiles
-            Collections.sort(pkgs);
-            size = pkgs.size();
-            // For a profile, if there are no packages to be documented, do not add
-            // it to profilePackages map.
-            if (size > 0)
-                profilePackages.put(p.name, pkgs);
-            prev = pkgs;
-        }
-
-        // Generate profiles documentation if any profile contains any
-        // of the packages to be documented.
-        showProfiles = !prev.isEmpty();
-    }
-
     private void initPackages() {
         packages = new TreeSet<>(Arrays.asList(root.specifiedPackages()));
         for (ClassDoc aClass : root.specifiedClasses()) {
@@ -512,8 +437,6 @@
                 customTagStrs.add(os);
             } else if (opt.equals("-tagletpath")) {
                 tagletpath = os[1];
-            }  else if (opt.equals("-xprofilespath")) {
-                profilespath = os[1];
             } else if (opt.equals("-keywords")) {
                 keywords = true;
             } else if (opt.equals("-serialwarn")) {
@@ -527,6 +450,8 @@
                 String url = os[1];
                 String pkglisturl = os[2];
                 extern.link(url, pkglisturl, root, true);
+            } else if (opt.equals("-xdaccessinternalapi")) {
+                exportInternalAPI = true;
             }
         }
         if (docencoding == null) {
@@ -545,11 +470,6 @@
     public void setOptions() throws Fault {
         initPackages();
         setOptions(root.options());
-        try {
-            initProfiles();
-        } catch (Exception e) {
-            throw new DocletAbortException(e);
-        }
         setSpecificDocletOptions(root.options());
     }
 
@@ -578,9 +498,9 @@
      * either -tag or -taglet arguments.
      */
     private void initTagletManager(Set<String[]> customTagStrs) {
-        tagletManager = tagletManager == null ?
-            new TagletManager(nosince, showversion, showauthor, javafx, message) :
-            tagletManager;
+        tagletManager = (tagletManager == null)
+                ? new TagletManager(nosince, showversion, showauthor, javafx, exportInternalAPI, message)
+                : tagletManager;
         for (String[] args : customTagStrs) {
             if (args[0].equals("-taglet")) {
                 tagletManager.addCustomTag(args[1], getFileManager(), tagletpath);
@@ -719,17 +639,6 @@
     }
 
     /**
-     * Check the validity of the given profile. Return false if there are no
-     * valid packages to be documented for the profile.
-     *
-     * @param profileName the profile that needs to be validated.
-     * @return true if the profile has valid packages to be documented.
-     */
-    public boolean shouldDocumentProfile(String profileName) {
-        return profilePackages.containsKey(profileName);
-    }
-
-    /**
      * Check the validity of the given Source or Output File encoding on this
      * platform.
      *
@@ -977,4 +886,6 @@
     }
 
     public abstract boolean showMessage(SourcePosition pos, String key);
+
+    public abstract Location getLocationForPackage(PackageDoc pd);
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java
deleted file mode 100644
index 5433552..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.internal.toolkit;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-
-/**
- * The interface for writing profile package summary output.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-
-public interface ProfilePackageSummaryWriter {
-
-    /**
-     * Get the header for the summary.
-     *
-     * @param heading Package name.
-     * @return the header to be added to the content tree
-     */
-    public abstract Content getPackageHeader(String heading);
-
-    /**
-     * Get the header for the content.
-     *
-     * @return a content tree for the content header
-     */
-    public abstract Content getContentHeader();
-
-    /**
-     * Get the header for the package summary.
-     *
-     * @return a content tree with the package summary header
-     */
-    public abstract Content getSummaryHeader();
-
-    /**
-     * Adds the table of classes to the documentation tree.
-     *
-     * @param classes the array of classes to document.
-     * @param label the label for this table.
-     * @param tableSummary the summary string for the table
-     * @param tableHeader array of table headers
-     * @param summaryContentTree the content tree to which the summaries will be added
-     */
-    public abstract void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content summaryContentTree);
-
-    /**
-     * Adds the package description from the "packages.html" file to the documentation
-     * tree.
-     *
-     * @param packageContentTree the content tree to which the package description
-     *                           will be added
-     */
-    public abstract void addPackageDescription(Content packageContentTree);
-
-    /**
-     * Adds the tag information from the "packages.html" file to the documentation
-     * tree.
-     *
-     * @param packageContentTree the content tree to which the package tags will
-     *                           be added
-     */
-    public abstract void addPackageTags(Content packageContentTree);
-
-    /**
-     * Adds the tag information from the "packages.html" or "package-info.java" file to the
-     * documentation tree.
-     *
-     * @param contentTree the content tree to which the package content tree will be added
-     * @param packageContentTree the package content tree to be added
-     */
-    public abstract void addPackageContent(Content contentTree, Content packageContentTree);
-
-    /**
-     * Adds the footer to the documentation tree.
-     *
-     * @param contentTree the tree to which the footer will be added
-     */
-    public abstract void addPackageFooter(Content contentTree);
-
-    /**
-     * Print the package summary document.
-     *
-     * @param contentTree the content tree that will be printed
-     */
-    public abstract void printDocument(Content contentTree) throws IOException;
-
-    /**
-     * Close the writer.
-     */
-    public abstract void close() throws IOException;
-
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java
index 985fb64..865049f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -26,7 +26,6 @@
 package com.sun.tools.doclets.internal.toolkit;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
 /**
@@ -66,33 +65,6 @@
     throws Exception;
 
     /**
-     * Return the writer for the profile summary.
-     *
-     * @param profile the profile being documented.
-     * @param prevProfile the previous profile that was documented.
-     * @param nextProfile the next profile being documented.
-     * @return the writer for the profile summary.  Return null if this
-     * writer is not supported by the doclet.
-     */
-    public abstract ProfileSummaryWriter getProfileSummaryWriter(Profile
-        profile, Profile prevProfile, Profile nextProfile)
-    throws Exception;
-
-    /**
-     * Return the writer for the profile package summary.
-     *
-     * @param packageDoc the profile package being documented.
-     * @param prevPkg the previous profile package that was documented.
-     * @param nextPkg the next profile package being documented.
-     * @param profile the profile being documented.
-     * @return the writer for the profile package summary.  Return null if this
-     * writer is not supported by the doclet.
-     */
-    public abstract ProfilePackageSummaryWriter getProfilePackageSummaryWriter(
-            PackageDoc packageDoc, PackageDoc prevPkg, PackageDoc nextPkg,
-            Profile profile) throws Exception;
-
-    /**
      * Return the writer for a class.
      *
      * @param classDoc the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
index d6c7ba9..a95e081 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -123,7 +123,7 @@
     /**
      * Build the documentation.
      *
-     * @throws IOException there was a problem writing the output.
+     * @throws IOException if there was a problem writing the output.
      */
     public abstract void build() throws IOException;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java
index 75181a4..972fc9e 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -29,7 +29,6 @@
 import java.util.Set;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
@@ -97,36 +96,6 @@
     }
 
     /**
-     * Return the builder that builds the profile summary.
-     *
-     * @param profile the profile being documented.
-     * @param prevProfile the previous profile being documented.
-     * @param nextProfile the next profile being documented.
-     * @return the builder that builds the profile summary.
-     */
-    public AbstractBuilder getProfileSummaryBuilder(Profile profile, Profile prevProfile,
-            Profile nextProfile) throws Exception {
-        return ProfileSummaryBuilder.getInstance(context, profile,
-            writerFactory.getProfileSummaryWriter(profile, prevProfile, nextProfile));
-    }
-
-    /**
-     * Return the builder that builds the profile package summary.
-     *
-     * @param pkg the profile package being documented.
-     * @param prevPkg the previous profile package being documented.
-     * @param nextPkg the next profile package being documented.
-     * @param profile the profile being documented.
-     * @return the builder that builds the profile package summary.
-     */
-    public AbstractBuilder getProfilePackageSummaryBuilder(PackageDoc pkg, PackageDoc prevPkg,
-            PackageDoc nextPkg, Profile profile) throws Exception {
-        return ProfilePackageSummaryBuilder.getInstance(context, pkg,
-            writerFactory.getProfilePackageSummaryWriter(pkg, prevPkg, nextPkg,
-                profile), profile);
-    }
-
-    /**
      * Return the builder for the class.
      *
      * @param classDoc the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java
deleted file mode 100644
index afc0b2c..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.internal.toolkit.builders;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.internal.toolkit.*;
-
-/**
- * Builds the summary for a given profile package.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageSummaryBuilder extends AbstractBuilder {
-    /**
-     * The root element of the profile package summary XML is {@value}.
-     */
-    public static final String ROOT = "PackageDoc";
-
-    /**
-     * The profile package being documented.
-     */
-    private final PackageDoc packageDoc;
-
-    /**
-     * The name of the profile being documented.
-     */
-    private final String profileName;
-
-    /**
-     * The value of the profile being documented.
-     */
-    private final int profileValue;
-
-    /**
-     * The doclet specific writer that will output the result.
-     */
-    private final ProfilePackageSummaryWriter profilePackageWriter;
-
-    /**
-     * The content that will be added to the profile package summary documentation tree.
-     */
-    private Content contentTree;
-
-    /**
-     * Construct a new ProfilePackageSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param pkg the profile package being documented.
-     * @param profilePackageWriter the doclet specific writer that will output the
-     *        result.
-     * @param profile the profile being documented.
-     */
-    private ProfilePackageSummaryBuilder(Context context,
-            PackageDoc pkg, ProfilePackageSummaryWriter profilePackageWriter,
-            Profile profile) {
-        super(context);
-        this.packageDoc = pkg;
-        this.profilePackageWriter = profilePackageWriter;
-        this.profileName = profile.name;
-        this.profileValue = profile.value;
-    }
-
-    /**
-     * Construct a new ProfilePackageSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param pkg the profile package being documented.
-     * @param profilePackageWriter the doclet specific writer that will output the
-     *        result.
-     * @param profile the profile being documented.
-     *
-     * @return an instance of a ProfilePackageSummaryBuilder.
-     */
-    public static ProfilePackageSummaryBuilder getInstance(Context context,
-            PackageDoc pkg, ProfilePackageSummaryWriter profilePackageWriter,
-            Profile profile) {
-        return new ProfilePackageSummaryBuilder(context, pkg, profilePackageWriter,
-                profile);
-    }
-
-    /**
-     * Build the profile package summary.
-     */
-    public void build() throws IOException {
-        if (profilePackageWriter == null) {
-            //Doclet does not support this output.
-            return;
-        }
-        build(layoutParser.parseXML(ROOT), contentTree);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return ROOT;
-    }
-
-    /**
-     * Build the profile package documentation.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the documentation will be added
-     */
-    public void buildPackageDoc(XMLNode node, Content contentTree) throws Exception {
-        contentTree = profilePackageWriter.getPackageHeader(
-                utils.getPackageName(packageDoc));
-        buildChildren(node, contentTree);
-        profilePackageWriter.addPackageFooter(contentTree);
-        profilePackageWriter.printDocument(contentTree);
-        profilePackageWriter.close();
-        utils.copyDocFiles(configuration, packageDoc);
-    }
-
-    /**
-     * Build the content for the profile package doc.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the package contents
-     *                    will be added
-     */
-    public void buildContent(XMLNode node, Content contentTree) {
-        Content packageContentTree = profilePackageWriter.getContentHeader();
-        buildChildren(node, packageContentTree);
-        profilePackageWriter.addPackageContent(contentTree, packageContentTree);
-    }
-
-    /**
-     * Build the profile package summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageContentTree the package content tree to which the summaries will
-     *                           be added
-     */
-    public void buildSummary(XMLNode node, Content packageContentTree) {
-        Content summaryContentTree = profilePackageWriter.getSummaryHeader();
-        buildChildren(node, summaryContentTree);
-        packageContentTree.addContent(summaryContentTree);
-    }
-
-    /**
-     * Build the summary for the interfaces in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the interface summary
-     *                           will be added
-     */
-    public void buildInterfaceSummary(XMLNode node, Content summaryContentTree) {
-        String interfaceTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Interface_Summary"),
-                configuration.getText("doclet.interfaces"));
-        String[] interfaceTableHeader = new String[] {
-            configuration.getText("doclet.Interface"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] interfaces =
-                packageDoc.isIncluded()
-                        ? packageDoc.interfaces()
-                        : configuration.classDocCatalog.interfaces(
-                                utils.getPackageName(packageDoc));
-        if (interfaces.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    interfaces,
-                    configuration.getText("doclet.Interface_Summary"),
-                    interfaceTableSummary, interfaceTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the classes in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the class summary will
-     *                           be added
-     */
-    public void buildClassSummary(XMLNode node, Content summaryContentTree) {
-        String classTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Class_Summary"),
-                configuration.getText("doclet.classes"));
-        String[] classTableHeader = new String[] {
-            configuration.getText("doclet.Class"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] classes =
-                packageDoc.isIncluded()
-                        ? packageDoc.ordinaryClasses()
-                        : configuration.classDocCatalog.ordinaryClasses(
-                                utils.getPackageName(packageDoc));
-        if (classes.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    classes,
-                    configuration.getText("doclet.Class_Summary"),
-                    classTableSummary, classTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the enums in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the enum summary will
-     *                           be added
-     */
-    public void buildEnumSummary(XMLNode node, Content summaryContentTree) {
-        String enumTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Enum_Summary"),
-                configuration.getText("doclet.enums"));
-        String[] enumTableHeader = new String[] {
-            configuration.getText("doclet.Enum"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] enums =
-                packageDoc.isIncluded()
-                        ? packageDoc.enums()
-                        : configuration.classDocCatalog.enums(
-                                utils.getPackageName(packageDoc));
-        if (enums.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    enums,
-                    configuration.getText("doclet.Enum_Summary"),
-                    enumTableSummary, enumTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the exceptions in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the exception summary will
-     *                           be added
-     */
-    public void buildExceptionSummary(XMLNode node, Content summaryContentTree) {
-        String exceptionTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Exception_Summary"),
-                configuration.getText("doclet.exceptions"));
-        String[] exceptionTableHeader = new String[] {
-            configuration.getText("doclet.Exception"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] exceptions =
-                packageDoc.isIncluded()
-                        ? packageDoc.exceptions()
-                        : configuration.classDocCatalog.exceptions(
-                                utils.getPackageName(packageDoc));
-        if (exceptions.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    exceptions,
-                    configuration.getText("doclet.Exception_Summary"),
-                    exceptionTableSummary, exceptionTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the errors in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the error summary will
-     *                           be added
-     */
-    public void buildErrorSummary(XMLNode node, Content summaryContentTree) {
-        String errorTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Error_Summary"),
-                configuration.getText("doclet.errors"));
-        String[] errorTableHeader = new String[] {
-            configuration.getText("doclet.Error"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] errors =
-                packageDoc.isIncluded()
-                        ? packageDoc.errors()
-                        : configuration.classDocCatalog.errors(
-                                utils.getPackageName(packageDoc));
-        if (errors.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    errors,
-                    configuration.getText("doclet.Error_Summary"),
-                    errorTableSummary, errorTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the annotation type in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the annotation type
-     *                           summary will be added
-     */
-    public void buildAnnotationTypeSummary(XMLNode node, Content summaryContentTree) {
-        String annotationtypeTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Annotation_Types_Summary"),
-                configuration.getText("doclet.annotationtypes"));
-        String[] annotationtypeTableHeader = new String[] {
-            configuration.getText("doclet.AnnotationType"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] annotationTypes =
-                packageDoc.isIncluded()
-                        ? packageDoc.annotationTypes()
-                        : configuration.classDocCatalog.annotationTypes(
-                                utils.getPackageName(packageDoc));
-        if (annotationTypes.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    annotationTypes,
-                    configuration.getText("doclet.Annotation_Types_Summary"),
-                    annotationtypeTableSummary, annotationtypeTableHeader,
-                    summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the description of the summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageContentTree the tree to which the package description will
-     *                           be added
-     */
-    public void buildPackageDescription(XMLNode node, Content packageContentTree) {
-        if (configuration.nocomment) {
-            return;
-        }
-        profilePackageWriter.addPackageDescription(packageContentTree);
-    }
-
-    /**
-     * Build the tags of the summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageContentTree the tree to which the package tags will be added
-     */
-    public void buildPackageTags(XMLNode node, Content packageContentTree) {
-        if (configuration.nocomment) {
-            return;
-        }
-        profilePackageWriter.addPackageTags(packageContentTree);
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java
deleted file mode 100644
index 91faf6f..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-
-package com.sun.tools.doclets.internal.toolkit.builders;
-
-import java.io.IOException;
-import java.util.List;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Builds the summary for a given profile.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfileSummaryBuilder extends AbstractBuilder {
-    /**
-     * The root element of the profile summary XML is {@value}.
-     */
-    public static final String ROOT = "ProfileDoc";
-
-    /**
-     * The profile being documented.
-     */
-    private final Profile profile;
-
-    /**
-     * The doclet specific writer that will output the result.
-     */
-    private final ProfileSummaryWriter profileWriter;
-
-    /**
-     * The content that will be added to the profile summary documentation tree.
-     */
-    private Content contentTree;
-
-    /**
-     * The profile package being documented.
-     */
-    private PackageDoc pkg;
-
-    /**
-     * Construct a new ProfileSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param profile the profile being documented.
-     * @param profileWriter the doclet specific writer that will output the
-     *        result.
-     */
-    private ProfileSummaryBuilder(Context context,
-            Profile profile, ProfileSummaryWriter profileWriter) {
-        super(context);
-        this.profile = profile;
-        this.profileWriter = profileWriter;
-    }
-
-    /**
-     * Construct a new ProfileSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param profile the profile being documented.
-     * @param profileWriter the doclet specific writer that will output the
-     *        result.
-     *
-     * @return an instance of a ProfileSummaryBuilder.
-     */
-    public static ProfileSummaryBuilder getInstance(Context context,
-            Profile profile, ProfileSummaryWriter profileWriter) {
-        return new ProfileSummaryBuilder(context, profile, profileWriter);
-    }
-
-    /**
-     * Build the profile summary.
-     */
-    public void build() throws IOException {
-        if (profileWriter == null) {
-            //Doclet does not support this output.
-            return;
-        }
-        build(layoutParser.parseXML(ROOT), contentTree);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return ROOT;
-    }
-
-    /**
-     * Build the profile documentation.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the documentation will be added
-     */
-    public void buildProfileDoc(XMLNode node, Content contentTree) throws Exception {
-        contentTree = profileWriter.getProfileHeader(profile.name);
-        buildChildren(node, contentTree);
-        profileWriter.addProfileFooter(contentTree);
-        profileWriter.printDocument(contentTree);
-        profileWriter.close();
-        utils.copyDocFiles(configuration, DocPaths.profileSummary(profile.name));
-    }
-
-    /**
-     * Build the content for the profile doc.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the profile contents
-     *                    will be added
-     */
-    public void buildContent(XMLNode node, Content contentTree) {
-        Content profileContentTree = profileWriter.getContentHeader();
-        buildChildren(node, profileContentTree);
-        profileWriter.addProfileContent(contentTree, profileContentTree);
-    }
-
-    /**
-     * Build the profile summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param profileContentTree the profile content tree to which the summaries will
-     *                           be added
-     */
-    public void buildSummary(XMLNode node, Content profileContentTree) {
-        Content summaryContentTree = profileWriter.getSummaryHeader();
-        buildChildren(node, summaryContentTree);
-        profileContentTree.addContent(profileWriter.getSummaryTree(summaryContentTree));
-    }
-
-    /**
-     * Build the profile package summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the content tree to which the summaries will
-     *                           be added
-     */
-    public void buildPackageSummary(XMLNode node, Content summaryContentTree) {
-        List<PackageDoc> packages = configuration.profilePackages.get(profile.name);
-        for (PackageDoc aPackage : packages) {
-            this.pkg = aPackage;
-            Content packageSummaryContentTree = profileWriter.getPackageSummaryHeader(this.pkg);
-            buildChildren(node, packageSummaryContentTree);
-            summaryContentTree.addContent(profileWriter.getPackageSummaryTree(
-                    packageSummaryContentTree));
-        }
-    }
-
-    /**
-     * Build the summary for the interfaces in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the interface summary
-     *                           will be added
-     */
-    public void buildInterfaceSummary(XMLNode node, Content packageSummaryContentTree) {
-        String interfaceTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Interface_Summary"),
-                configuration.getText("doclet.interfaces"));
-        String[] interfaceTableHeader = new String[] {
-            configuration.getText("doclet.Interface"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] interfaces = pkg.interfaces();
-        if (interfaces.length > 0) {
-            profileWriter.addClassesSummary(
-                    interfaces,
-                    configuration.getText("doclet.Interface_Summary"),
-                    interfaceTableSummary, interfaceTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the classes in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the class summary will
-     *                           be added
-     */
-    public void buildClassSummary(XMLNode node, Content packageSummaryContentTree) {
-        String classTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Class_Summary"),
-                configuration.getText("doclet.classes"));
-        String[] classTableHeader = new String[] {
-            configuration.getText("doclet.Class"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] classes = pkg.ordinaryClasses();
-        if (classes.length > 0) {
-            profileWriter.addClassesSummary(
-                    classes,
-                    configuration.getText("doclet.Class_Summary"),
-                    classTableSummary, classTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the enums in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the enum summary will
-     *                           be added
-     */
-    public void buildEnumSummary(XMLNode node, Content packageSummaryContentTree) {
-        String enumTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Enum_Summary"),
-                configuration.getText("doclet.enums"));
-        String[] enumTableHeader = new String[] {
-            configuration.getText("doclet.Enum"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] enums = pkg.enums();
-        if (enums.length > 0) {
-            profileWriter.addClassesSummary(
-                    enums,
-                    configuration.getText("doclet.Enum_Summary"),
-                    enumTableSummary, enumTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the exceptions in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the exception summary will
-     *                           be added
-     */
-    public void buildExceptionSummary(XMLNode node, Content packageSummaryContentTree) {
-        String exceptionTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Exception_Summary"),
-                configuration.getText("doclet.exceptions"));
-        String[] exceptionTableHeader = new String[] {
-            configuration.getText("doclet.Exception"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] exceptions = pkg.exceptions();
-        if (exceptions.length > 0) {
-            profileWriter.addClassesSummary(
-                    exceptions,
-                    configuration.getText("doclet.Exception_Summary"),
-                    exceptionTableSummary, exceptionTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the errors in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the error summary will
-     *                           be added
-     */
-    public void buildErrorSummary(XMLNode node, Content packageSummaryContentTree) {
-        String errorTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Error_Summary"),
-                configuration.getText("doclet.errors"));
-        String[] errorTableHeader = new String[] {
-            configuration.getText("doclet.Error"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] errors = pkg.errors();
-        if (errors.length > 0) {
-            profileWriter.addClassesSummary(
-                    errors,
-                    configuration.getText("doclet.Error_Summary"),
-                    errorTableSummary, errorTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the annotation type in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the annotation type
-     *                           summary will be added
-     */
-    public void buildAnnotationTypeSummary(XMLNode node, Content packageSummaryContentTree) {
-        String annotationtypeTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Annotation_Types_Summary"),
-                configuration.getText("doclet.annotationtypes"));
-        String[] annotationtypeTableHeader = new String[] {
-            configuration.getText("doclet.AnnotationType"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] annotationTypes = pkg.annotationTypes();
-        if (annotationTypes.length > 0) {
-            profileWriter.addClassesSummary(
-                    annotationTypes,
-                    configuration.getText("doclet.Annotation_Types_Summary"),
-                    annotationtypeTableSummary, annotationtypeTableHeader,
-                    packageSummaryContentTree);
-        }
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml
index f7f2f9c..3cbe582 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='utf-8'?>
 
 <!--
- Copyright (c) 2003, 2013, 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
@@ -28,21 +28,6 @@
 
 <Doclet>
 
-    <ProfileDoc>
-        <Content>
-            <Summary>
-                <PackageSummary>
-                    <InterfaceSummary/>
-                    <ClassSummary/>
-                    <EnumSummary/>
-                    <ExceptionSummary/>
-                    <ErrorSummary/>
-                    <AnnotationTypeSummary/>
-                </PackageSummary>
-            </Summary>
-        </Content>
-    </ProfileDoc>
-
     <PackageDoc>
         <Content>
             <Summary>
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
index f6e10be..84e44b3 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
@@ -31,7 +31,6 @@
 doclet.Building_Index_For_All_Classes=Building index for all classes...
 doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
 doclet.Packages=Packages
-doclet.Profiles=Profiles
 doclet.Other_Packages=Other Packages
 doclet.Notice_taglet_registered=Registered Taglet {0} ...
 doclet.Notice_taglet_unseen=Note: Custom tags that were not seen: {0}
@@ -69,7 +68,6 @@
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
 doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
-doclet.Profile_Summary=Profile Summary
 doclet.Interface_Summary=Interface Summary
 doclet.Annotation_Types_Summary=Annotation Types Summary
 doclet.Enum_Summary=Enum Summary
@@ -92,7 +90,6 @@
 doclet.Classes=Classes
 doclet.Packages=Packages
 doclet.packages=packages
-doclet.profiles=profiles
 doclet.All_Classes=All Classes
 doclet.All_Superinterfaces=All Superinterfaces:
 doclet.All_Implemented_Interfaces=All Implemented Interfaces:
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css
index 076087c..55b5109 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css
@@ -143,6 +143,9 @@
     font-size:11px;
     margin:0;
 }
+.navPadding {
+    padding-top: 100px;
+}
 .fixedNav {
     position:fixed;
     width:100%;
@@ -265,7 +268,6 @@
 .title {
     color:#2c4557;
     margin:10px 0;
-    padding-top:5.4em;
 }
 .subTitle {
     margin:5px 0 0 0;
@@ -610,7 +612,7 @@
     color:#474747;
 }
 .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
-.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
+.overrideSpecifyLabel, .packageHierarchyLabel, .packageLabelInClass, .paramLabel, .returnLabel,
 .seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink {
     font-weight:bold;
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
index ddb9289..bd4ff76 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, 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
@@ -163,6 +163,8 @@
      */
     private boolean javafx;
 
+    private boolean exportInternalAPI;
+
     /**
      * Construct a new <code>TagletManager</code>.
      * @param nosince true if we do not want to use @since tags.
@@ -172,6 +174,7 @@
      */
     public TagletManager(boolean nosince, boolean showversion,
                          boolean showauthor, boolean javafx,
+                         boolean exportInternalAPI,
                          MessageRetriever message) {
         overridenStandardTags = new HashSet<>();
         potentiallyConflictingTags = new HashSet<>();
@@ -183,6 +186,7 @@
         this.showversion = showversion;
         this.showauthor = showauthor;
         this.javafx = javafx;
+        this.exportInternalAPI = exportInternalAPI;
         this.message = message;
         initStandardTaglets();
         initStandardTagsLowercase();
@@ -233,7 +237,13 @@
                 tagClassLoader = new URLClassLoader(pathToURLs(cpString));
             }
 
+            if (exportInternalAPI) {
+                exportInternalAPI(tagClassLoader);
+            }
+
             customTagClass = tagClassLoader.loadClass(classname);
+            ensureReadable(customTagClass);
+
             Method meth = customTagClass.getMethod("register",
                                                    Map.class);
             Object[] list = customTags.values().toArray();
@@ -253,11 +263,71 @@
                 }
             }
         } catch (Exception exc) {
+            exc.printStackTrace();
             message.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname);
         }
 
     }
 
+    /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Export javadoc internal API to the unnamed module for a classloader.
+     * This is to support continued use of existing non-standard doclets that
+     * use the internal toolkit API and related classes.
+     * @param cl the classloader
+     */
+    private void exportInternalAPI(ClassLoader cl) {
+        String[] packages = {
+            "com.sun.tools.doclets",
+            "com.sun.tools.doclets.standard",
+            "com.sun.tools.doclets.internal.toolkit",
+            "com.sun.tools.doclets.internal.toolkit.taglets",
+            "com.sun.tools.doclets.internal.toolkit.builders",
+            "com.sun.tools.doclets.internal.toolkit.util",
+            "com.sun.tools.doclets.internal.toolkit.util.links",
+            "com.sun.tools.doclets.formats.html",
+            "com.sun.tools.doclets.formats.html.markup"
+        };
+
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(getClass());
+
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            Method addExportsMethod = moduleClass.getDeclaredMethod("addExports", String.class, moduleClass);
+
+            Method getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule");
+            Object target = getUnnamedModuleMethod.invoke(cl);
+
+            for (String pack : packages) {
+                addExportsMethod.invoke(thisModule, pack, target);
+            }
+        } catch (Exception e) {
+            // do nothing
+            e.printStackTrace();
+        }
+    }
+
     private String appendPath(String path1, String path2) {
         if (path1 == null || path1.length() == 0) {
             return path2 == null ? "." : path2;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
index 7c0b88d..8b71150 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
@@ -25,6 +25,9 @@
 
 package com.sun.tools.doclets.internal.toolkit.util;
 
+import java.util.Map;
+import java.util.WeakHashMap;
+
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
@@ -42,13 +45,15 @@
  *
  * @since 1.8
  */
-public abstract class DocFileFactory {
+abstract class DocFileFactory {
+    private static final Map<Configuration, DocFileFactory> factories = new WeakHashMap<>();
+
     /**
      * Get the appropriate factory, based on the file manager given in the
      * configuration.
      */
     static synchronized DocFileFactory getFactory(Configuration configuration) {
-        DocFileFactory f = configuration.docFileFactory;
+        DocFileFactory f = factories.get(configuration);
         if (f == null) {
             JavaFileManager fm = configuration.getFileManager();
             if (fm instanceof StandardJavaFileManager) {
@@ -56,7 +61,7 @@
             } else {
                 throw new IllegalStateException();
             }
-            configuration.docFileFactory = f;
+            factories.put(configuration, f);
         }
         return f;
     }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java
index 9da6ac6..06e5b27 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -147,26 +147,6 @@
     /** The name of the file for the overview frame. */
     public static final DocPath PROFILE_OVERVIEW_FRAME = DocPath.create("profile-overview-frame.html");
 
-    /** The name of the file for the profile frame. */
-     public static DocPath profileFrame(String profileName) {
-        return DocPath.create(profileName + "-frame.html");
-    }
-
-    /** The name of the file for the profile package frame. */
-     public static DocPath profilePackageFrame(String profileName) {
-        return DocPath.create(profileName + "-package-frame.html");
-    }
-
-    /** The name of the file for the profile package summary. */
-     public static DocPath profilePackageSummary(String profileName) {
-        return DocPath.create(profileName + "-package-summary.html");
-    }
-
-    /** The name of the file for the profile summary. */
-     public static DocPath profileSummary(String profileName) {
-        return DocPath.create(profileName + "-summary.html");
-    }
-
     /** The name of the sub-package from which resources are read. */
     public static final DocPath RESOURCES = DocPath.create("resources");
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
index 350e807..88f3d92 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
@@ -80,7 +80,7 @@
 
         /**
          * The URL or the directory path at which the package documentation will be
-         * avaliable.
+         * available.
          */
         final String path;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java
index cf63a7f..5775899 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, 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
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 
 /**
@@ -108,20 +107,6 @@
     }
 
     /**
-     * Get the profile keywords.
-     *
-     * @param profile the profile being documented
-     */
-    public String[] getMetaKeywords(Profile profile) {
-        if( configuration.keywords ) {
-            String profileName = profile.name;
-            return new String[] { profileName + " " + "profile" };
-        } else {
-            return new String[] {};
-        }
-    }
-
-    /**
      * Get the overview keywords.
      */
     public String[] getOverviewMetaKeywords(String title, String docTitle) {
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
index 2c2941d..f20012a 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
@@ -105,12 +105,12 @@
 
     @Override
     Iterable<DocFile> list(Location location, DocPath path) {
-        if (location != StandardLocation.SOURCE_PATH)
-            throw new IllegalArgumentException();
+        Location l = ((location == StandardLocation.SOURCE_PATH)
+                && !fileManager.hasLocation(StandardLocation.SOURCE_PATH))
+                ? StandardLocation.CLASS_PATH
+                : location;
 
         Set<DocFile> files = new LinkedHashSet<>();
-        Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
         for (Path f: fileManager.getLocationAsPaths(l)) {
             if (Files.isDirectory(f)) {
                 f = f.resolve(path.getPath());
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java
index 7019a04..0a9acf8 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -32,6 +32,7 @@
 import java.text.Collator;
 import java.util.*;
 
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
 import com.sun.javadoc.*;
@@ -205,13 +206,14 @@
      * @param overwrite Overwrite files if true.
      */
     public void copyDocFiles(Configuration configuration, PackageDoc pd) {
-        copyDocFiles(configuration, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
+        Location locn = configuration.getLocationForPackage(pd);
+        copyDocFiles(configuration, locn, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
     }
 
-    public void copyDocFiles(Configuration configuration, DocPath dir) {
+    public void copyDocFiles(Configuration configuration, Location locn, DocPath dir) {
         try {
             boolean first = true;
-            for (DocFile f : DocFile.list(configuration, StandardLocation.SOURCE_PATH, dir)) {
+            for (DocFile f : DocFile.list(configuration, locn, dir)) {
                 if (!f.isDirectory()) {
                     continue;
                 }
@@ -237,7 +239,7 @@
                     } else if (srcfile.isDirectory()) {
                         if (configuration.copydocfilesubdirs
                                 && !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
-                            copyDocFiles(configuration, dir.resolve(srcfile.getName()));
+                            copyDocFiles(configuration, locn, dir.resolve(srcfile.getName()));
                         }
                     }
                 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java
index 7a1abfb..487215c 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java
@@ -101,9 +101,9 @@
     private final Configuration configuration;
     private final Utils utils;
 
-    private final Map<ClassDoc, ProgramElementDoc[]> propertiesCache;
-    private final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap;
-    private final Map<ProgramElementDoc, GetterSetter> getterSetterMap;
+    private static final Map<ClassDoc, ProgramElementDoc[]> propertiesCache = new HashMap<>();
+    private static final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap = new HashMap<>();
+    private static final Map<ProgramElementDoc, GetterSetter> getterSetterMap = new HashMap<>();
 
     /**
      * Construct a VisibleMemberMap of the given type for the given
@@ -123,9 +123,6 @@
         this.kind = kind;
         this.configuration = configuration;
         this.utils = configuration.utils;
-        propertiesCache = configuration.propertiesCache;
-        classPropertiesMap = configuration.classPropertiesMap;
-        getterSetterMap = configuration.getterSetterMap;
         new ClassMembers(classdoc, STARTLEVEL).build();
     }
 
@@ -716,7 +713,7 @@
         }
     }
 
-    public class GetterSetter {
+    private class GetterSetter {
         private final ProgramElementDoc getter;
         private final ProgramElementDoc setter;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
index d67cc78..acebdb8 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
@@ -89,7 +89,7 @@
 public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
 
     public final ClassType type;        // protected->public for debugging
-    protected final ClassSymbol tsym;
+    public final ClassSymbol tsym;
 
     boolean isIncluded = false;         // Set in RootDocImpl
 
@@ -1137,7 +1137,7 @@
 
         //### Add the implicit "import java.lang.*" to the result
         Names names = tsym.name.table.names;
-        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(names.java_lang)));
+        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(env.syms.java_base, names.java_lang)));
 
         Env<AttrContext> compenv = env.enter.getEnv(tsym);
         if (compenv == null) return new PackageDocImpl[0];
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
index 680f37f..2ac3652 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
@@ -52,6 +52,8 @@
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
+import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 
 /**
@@ -151,7 +153,7 @@
         finder = JavadocClassFinder.instance(context);
         enter = JavadocEnter.instance(context);
         names = Names.instance(context);
-        externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable"));
+        externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
         chk = Check.instance(context);
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
@@ -185,7 +187,9 @@
      */
     public ClassDocImpl loadClass(String name) {
         try {
-            ClassSymbol c = finder.loadClass(names.fromString(name));
+            Name nameImpl = names.fromString(name);
+            ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+            ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
             return getClassDoc(c);
         } catch (CompletionFailure ex) {
             chk.completionError(null, ex);
@@ -201,7 +205,9 @@
         //### to avoid a compiler bug.  Most likely
         //### instead a dummy created for error recovery.
         //### Should investigate this.
-        PackageSymbol p = syms.packages.get(names.fromString(name));
+        Name nameImpl = names.fromString(name);
+        ModuleSymbol mod = syms.inferModule(nameImpl);
+        PackageSymbol p = mod != null ? syms.getPackage(mod, nameImpl) : null;
         ClassSymbol c = getClassSymbol(name);
         if (p != null && c == null) {
             return getPackageDoc(p);
@@ -220,7 +226,9 @@
             char[] nameChars = name.toCharArray();
             int idx = name.length();
             for (;;) {
-                ClassSymbol s = syms.classes.get(names.fromChars(nameChars, 0, nameLen));
+                Name nameImpl = names.fromChars(nameChars, 0, nameLen);
+                ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+                ClassSymbol s = mod != null ? syms.getClass(mod, nameImpl) : null;
                 if (s != null)
                     return s; // found it!
                 idx = name.substring(0, idx).lastIndexOf('.');
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
index b432653..f41edba 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -74,6 +74,12 @@
      */
     private final boolean apiMode;
 
+    /**
+     * Whether javadoc internal API should be exported to doclets
+     * and (indirectly) to taglets
+     */
+    private final boolean exportInternalAPI;
+
     private static class DocletInvokeException extends Exception {
         private static final long serialVersionUID = 0;
     }
@@ -88,21 +94,30 @@
         }
     }
 
-    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode) {
+    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode, boolean exportInternalAPI) {
         this.messager = messager;
         this.docletClass = docletClass;
         docletClassName = docletClass.getName();
         appClassLoader = null;
         this.apiMode = apiMode;
+        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
+
+        ensureReadable(docletClass);
+        // this may not be soon enough if the class has already been loaded
+        if (exportInternalAPI) {
+            exportInternalAPI(docletClass.getClassLoader());
+        }
     }
 
     public DocletInvoker(Messager messager, JavaFileManager fileManager,
                          String docletClassName, String docletPath,
                          ClassLoader docletParentClassLoader,
-                         boolean apiMode) {
+                         boolean apiMode,
+                         boolean exportInternalAPI) {
         this.messager = messager;
         this.docletClassName = docletClassName;
         this.apiMode = apiMode;
+        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
 
         if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.DOCLET_PATH)) {
             appClassLoader = fileManager.getClassLoader(DocumentationTool.Location.DOCLET_PATH);
@@ -121,6 +136,10 @@
                 appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
         }
 
+        if (exportInternalAPI) {
+            exportInternalAPI(appClassLoader);
+        }
+
         // attempt to find doclet
         Class<?> dc = null;
         try {
@@ -130,6 +149,8 @@
             messager.exit();
         }
         docletClass = dc;
+
+        ensureReadable(docletClass);
     }
 
     /*
@@ -341,6 +362,64 @@
     }
 
     /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Export javadoc internal API to the unnamed module for a classloader.
+     * This is to support continued use of existing non-standard doclets that
+     * use the internal toolkit API and related classes.
+     * @param cl the classloader
+     */
+    private void exportInternalAPI(ClassLoader cl) {
+        String[] packages = {
+            "com.sun.tools.doclets",
+            "com.sun.tools.doclets.standard",
+            "com.sun.tools.doclets.internal.toolkit",
+            "com.sun.tools.doclets.internal.toolkit.taglets",
+            "com.sun.tools.doclets.internal.toolkit.builders",
+            "com.sun.tools.doclets.internal.toolkit.util",
+            "com.sun.tools.doclets.internal.toolkit.util.links",
+            "com.sun.tools.doclets.formats.html",
+            "com.sun.tools.doclets.formats.html.markup"
+        };
+
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(getClass());
+
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            Method addExportsMethod = moduleClass.getDeclaredMethod("addExports", String.class, moduleClass);
+
+            Method getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule");
+            Object target = getUnnamedModuleMethod.invoke(cl);
+
+            for (String pack : packages) {
+                addExportsMethod.invoke(thisModule, pack, target);
+            }
+        } catch (Exception e) {
+            // do nothing
+        }
+    }
+
+    /**
      * Utility method for converting a search path string to an array of directory and JAR file
      * URLs.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
index 617d4cd..b29c289 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
@@ -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
@@ -29,7 +29,6 @@
 import java.io.IOException;
 import java.util.Collection;
 import java.util.EnumSet;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -44,7 +43,7 @@
 
 import com.sun.tools.javac.code.ClassFinder;
 import com.sun.tools.javac.code.Symbol.Completer;
-import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -53,7 +52,6 @@
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Position;
 
 
 /**
@@ -92,6 +90,7 @@
     /**
      * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
      */
+    @Override
     protected boolean keepComments() {
         return true;
     }
@@ -100,28 +99,22 @@
      *  Construct a new javadoc tool.
      */
     public static JavadocTool make0(Context context) {
-        Messager messager = null;
-        try {
-            // force the use of Javadoc's class finder
-            JavadocClassFinder.preRegister(context);
+        // force the use of Javadoc's class finder
+        JavadocClassFinder.preRegister(context);
 
-            // force the use of Javadoc's own enter phase
-            JavadocEnter.preRegister(context);
+        // force the use of Javadoc's own enter phase
+        JavadocEnter.preRegister(context);
 
-            // force the use of Javadoc's own member enter phase
-            JavadocMemberEnter.preRegister(context);
+        // force the use of Javadoc's own member enter phase
+        JavadocMemberEnter.preRegister(context);
 
-            // force the use of Javadoc's own todo phase
-            JavadocTodo.preRegister(context);
+        // force the use of Javadoc's own todo phase
+        JavadocTodo.preRegister(context);
 
-            // force the use of Messager as a Log
-            messager = Messager.instance0(context);
+        // force the use of Messager as a Log
+        Messager.instance0(context);
 
-            return new JavadocTool(context);
-        } catch (CompletionFailure ex) {
-            messager.error(Position.NOPOS, ex.getMessage());
-            return null;
-        }
+        return new JavadocTool(context);
     }
 
     public RootDocImpl getRootDocImpl(String doclocale,
@@ -170,7 +163,11 @@
             // Parse the files and collect the package names.
             for (String arg: args) {
                 if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
-                    parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    if (new File(arg).getName().equals("module-info.java")) {
+                        docenv.warning(null, "main.file_ignored", arg);
+                    } else {
+                        parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    }
                 } else if (isValidPackageName(arg)) {
                     packageNames.add(arg);
                 } else if (arg.endsWith(".java")) {
@@ -185,10 +182,15 @@
 
             // Parse file objects provide via the DocumentationTool API
             parse(fileObjects, classTrees, true);
+            modules.enter(classTrees.toList(), null);
+
+            syms.unnamedModule.complete(); // TEMP to force reading all named modules
 
             // Build up the complete list of any packages to be documented
-            Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+            Location location =
+                    modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH
+                    : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH
+                    : StandardLocation.CLASS_PATH;
 
             PackageTable t = new PackageTable(docenv.fileManager, location)
                     .packages(packageNames)
@@ -206,6 +208,7 @@
                     messager.warning(Messager.NOPOS, "main.no_source_files_for_package", packageName);
                 parse(files, packageTrees, false);
             }
+            modules.enter(packageTrees.toList(), null);
 
             if (messager.nerrors() != 0) {
                 return null;
@@ -214,6 +217,7 @@
             // Enter symbols for all files
             docenv.notice("main.Building_tree");
             javadocEnter.main(classTrees.toList().appendList(packageTrees.toList()));
+            enterDone = true;
         } catch (Abort ex) {}
 
         if (messager.nerrors() != 0)
@@ -301,7 +305,7 @@
     /**
      * A table to manage included and excluded packages.
      */
-    static class PackageTable {
+    class PackageTable {
         private final Map<String, Entry> entries = new LinkedHashMap<>();
         private final Set<String> includedPackages = new LinkedHashSet<>();
         private final JavaFileManager fm;
@@ -331,8 +335,9 @@
             }
 
             for (String packageName: packageNames) {
-                for (JavaFileObject fo: fm.list(location, packageName, sourceKinds, true)) {
-                    String binaryName = fm.inferBinaryName(location, fo);
+                Location packageLocn = getLocation(packageName);
+                for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, true)) {
+                    String binaryName = fm.inferBinaryName(packageLocn, fo);
                     String pn = getPackageName(binaryName);
                     String simpleName = getSimpleName(binaryName);
                     Entry e = getEntry(pn);
@@ -366,8 +371,9 @@
                 return e.files;
 
             ListBuffer<JavaFileObject> lb = new ListBuffer<>();
-            for (JavaFileObject fo: fm.list(location, packageName, sourceKinds, false)) {
-                String binaryName = fm.inferBinaryName(location, fo);
+            Location packageLocn = getLocation(packageName);
+            for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) {
+                String binaryName = fm.inferBinaryName(packageLocn, fo);
                 String simpleName = getSimpleName(binaryName);
                 if (isValidClassName(simpleName)) {
                     lb.append(fo);
@@ -377,6 +383,15 @@
             return lb.toList();
         }
 
+        private Location getLocation(String packageName) throws IOException {
+            if (location == StandardLocation.MODULE_SOURCE_PATH) {
+                // TODO: handle invalid results
+                ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
+                return fm.getModuleLocation(location, msym.name.toString());
+            } else {
+                return location;
+            }
+        }
 
         private Entry getEntry(String name) {
             Entry e = entries.get(name);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
index fcc5efd..1375395 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -64,7 +64,7 @@
 
 public class PackageDocImpl extends DocImpl implements PackageDoc {
 
-    protected PackageSymbol sym;
+    public final PackageSymbol sym;
     private JCCompilationUnit tree = null;    // for source position
 
     public FileObject docPath = null;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
index 9e3419f..c057625 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
@@ -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
@@ -313,7 +313,11 @@
                     setOption(arg);
                     o.process(this);
                 }
-
+            } else if (arg.equals("-XDaccessInternalAPI")) {
+                // pass this hidden option down to the doclet, if it wants it
+                if (docletInvoker.optionLength("-XDaccessInternalAPI") == 1) {
+                    setOption(arg);
+                }
             } else if (arg.startsWith("-XD")) {
                 // hidden javac options
                 String s = arg.substring("-XD".length());
@@ -461,12 +465,7 @@
      * @param argv Args containing -doclet and -docletpath, in case they are required.
      */
     private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) {
-        if (docletClass != null) {
-            docletInvoker = new DocletInvoker(messager, docletClass, apiMode);
-            // TODO, check no -doclet, -docletpath
-            return;
-        }
-
+        boolean exportInternalAPI = false;
         String docletClassName = null;
         String docletPath = null;
 
@@ -487,18 +486,26 @@
                 } else {
                     docletPath += File.pathSeparator + argv[i];
                 }
+            } else if (arg.equals("-XDaccessInternalAPI")) {
+                exportInternalAPI = true;
             }
         }
 
-        if (docletClassName == null) {
-            docletClassName = defaultDocletClassName;
-        }
+        if (docletClass != null) {
+            // TODO, check no -doclet, -docletpath
+            docletInvoker = new DocletInvoker(messager, docletClass, apiMode, exportInternalAPI);
+        } else {
+            if (docletClassName == null) {
+                docletClassName = defaultDocletClassName;
+            }
 
-        // attempt to find doclet
-        docletInvoker = new DocletInvoker(messager, fileManager,
-                docletClassName, docletPath,
-                docletParentClassLoader,
-                apiMode);
+            // attempt to find doclet
+            docletInvoker = new DocletInvoker(messager, fileManager,
+                    docletClassName, docletPath,
+                    docletParentClassLoader,
+                    apiMode,
+                    exportInternalAPI);
+        }
     }
 
     /**
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
index 6c3b417..18ab44f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,6 +88,48 @@
         }
     },
 
+    MODULESOURCEPATH("-modulesourcepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULESOURCEPATH, arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.UPGRADEMODULEPATH, arg);
+        }
+    },
+
+    SYSTEM("-system", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SYSTEM, arg);
+        }
+    },
+
+    MODULEPATH("-modulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULEPATH, arg);
+        }
+    },
+
+    ADDMODS("-addmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    LIMITMODS("-limitmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
     ENCODING("-encoding", true) {
         @Override
         public void process(Helper helper, String arg) {
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
index 105ab1c..dbd4993 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
@@ -91,6 +91,7 @@
 main.illegal_locale_name=Locale not available: {0}
 main.malformed_locale_name=Malformed locale name: {0}
 main.file_not_found=File not found: "{0}"
+main.file_ignored=File ignored: "{0}" (not yet supported)
 main.illegal_class_name=Illegal class name: "{0}"
 main.illegal_package_name=Illegal package name: "{0}"
 main.release.bootclasspath.conflict=option {0} cannot be used together with -release
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
similarity index 60%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java
rename to langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
index f8928c2..457fe16 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -23,19 +23,27 @@
  * questions.
  */
 
-package com.sun.tools.doclets.formats.html;
+package jdk.javadoc.internal.doclets.formats.html;
 
 import java.io.*;
+import java.util.Map;
+import java.util.Set;
 
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.DocPath;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 
 /**
- * Abstract class to generate the profile overview files in
+ * Abstract class to generate the module overview files in
  * Frame and Non-Frame format. This will be sub-classed to
- * generate profile-overview-frame.html as well as profile-overview-summary.html.
+ * generate module-overview-frame.html as well as module-overview-summary.html.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
@@ -44,23 +52,23 @@
  *
  * @author Bhavesh Patel
  */
-public abstract class AbstractProfileIndexWriter extends HtmlDocletWriter {
+public abstract class AbstractModuleIndexWriter extends HtmlDocletWriter {
 
     /**
-     * Profiles to be documented.
+     * Modules to be documented.
      */
-    protected Profiles profiles;
+    protected Map<ModuleElement, Set<PackageElement>> modules;
 
     /**
-     * Constructor. Also initializes the profiles variable.
+     * Constructor. Also initializes the modules variable.
      *
      * @param configuration  The current configuration
-     * @param filename Name of the profile index file to be generated.
+     * @param filename Name of the module index file to be generated.
      */
-    public AbstractProfileIndexWriter(ConfigurationImpl configuration,
+    public AbstractModuleIndexWriter(ConfigurationImpl configuration,
                                       DocPath filename) throws IOException {
         super(configuration, filename);
-        profiles = configuration.profiles;
+        modules = configuration.modulePackages;
     }
 
     /**
@@ -85,37 +93,37 @@
     protected abstract void addOverviewHeader(Content body);
 
     /**
-     * Adds the profiles list to the documentation tree.
+     * Adds the modules list to the documentation tree.
      *
-     * @param profiles profiles object
+     * @param modules the set of modules
      * @param text caption for the table
      * @param tableSummary summary for the table
-     * @param body the document tree to which the profiles list will be added
+     * @param body the document tree to which the modules list will be added
      */
-    protected abstract void addProfilesList(Profiles profiles, String text,
+    protected abstract void addModulesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
             String tableSummary, Content body);
 
     /**
-     * Adds the profile packages list to the documentation tree.
+     * Adds the module packages list to the documentation tree.
      *
-     * @param profiles profiles object
+     * @param modules the set of modules
      * @param text caption for the table
      * @param tableSummary summary for the table
-     * @param body the document tree to which the profiles list will be added
-     * @param profileName the name for the profile being documented
+     * @param body the document tree to which the modules list will be added
+     * @param mdle the module being documented
      */
-    protected abstract void addProfilePackagesList(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName);
+    protected abstract void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle);
 
     /**
-     * Generate and prints the contents in the profile index file. Call appropriate
+     * Generate and prints the contents in the module index file. Call appropriate
      * methods from the sub-class in order to generate Frame or Non
      * Frame format.
      *
      * @param title the title of the window.
      * @param includeScript boolean set true if windowtitle script is to be included
      */
-    protected void buildProfileIndexFile(String title, boolean includeScript) throws IOException {
+    protected void buildModuleIndexFile(String title, boolean includeScript) throws IOException {
         String windowOverview = configuration.getText(title);
         Content body = getBody(includeScript, getWindowTitle(windowOverview));
         addNavigationBarHeader(body);
@@ -128,21 +136,21 @@
     }
 
     /**
-     * Generate and prints the contents in the profile packages index file. Call appropriate
+     * Generate and prints the contents in the module packages index file. Call appropriate
      * methods from the sub-class in order to generate Frame or Non
      * Frame format.
      *
      * @param title the title of the window.
      * @param includeScript boolean set true if windowtitle script is to be included
-     * @param profileName the name of the profile being documented
+     * @param moduleName the name of the module being documented
      */
-    protected void buildProfilePackagesIndexFile(String title,
-            boolean includeScript, String profileName) throws IOException {
+    protected void buildModulePackagesIndexFile(String title,
+            boolean includeScript, ModuleElement mdle) throws IOException {
         String windowOverview = configuration.getText(title);
         Content body = getBody(includeScript, getWindowTitle(windowOverview));
         addNavigationBarHeader(body);
         addOverviewHeader(body);
-        addProfilePackagesIndex(body, profileName);
+        addModulePackagesIndex(body, mdle);
         addOverview(body);
         addNavigationBarFooter(body);
         printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title,
@@ -158,67 +166,41 @@
     }
 
     /**
-     * Adds the frame or non-frame profile index to the documentation tree.
+     * Adds the frame or non-frame module index to the documentation tree.
      *
      * @param body the document tree to which the index will be added
      */
     protected void addIndex(Content body) {
-        addIndexContents(profiles, "doclet.Profile_Summary",
+        addIndexContents(modules, "doclet.Module_Summary",
                 configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Profile_Summary"),
-                configuration.getText("doclet.profiles")), body);
+                configuration.getText("doclet.Module_Summary"),
+                configuration.getText("doclet.modules")), body);
     }
 
     /**
-     * Adds the frame or non-frame profile packages index to the documentation tree.
+     * Adds the frame or non-frame module packages index to the documentation tree.
      *
      * @param body the document tree to which the index will be added
-     * @param profileName  the name of the profile being documented
+     * @param mdle the module being documented
      */
-    protected void addProfilePackagesIndex(Content body, String profileName) {
-        addProfilePackagesIndexContents(profiles, "doclet.Profile_Summary",
+    protected void addModulePackagesIndex(Content body, ModuleElement mdle) {
+        addModulePackagesIndexContents("doclet.Module_Summary",
                 configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Profile_Summary"),
-                configuration.getText("doclet.profiles")), body, profileName);
+                configuration.getText("doclet.Module_Summary"),
+                configuration.getText("doclet.modules")), body, mdle);
     }
 
     /**
-     * Adds profile index contents. Call appropriate methods from
+     * Adds module index contents. Call appropriate methods from
      * the sub-classes. Adds it to the body HtmlTree
      *
-     * @param profiles profiles to be documented
+     * @param modules the modules to be documented
      * @param text string which will be used as the heading
      * @param tableSummary summary for the table
      * @param body the document tree to which the index contents will be added
      */
-    protected void addIndexContents(Profiles profiles, String text,
+    protected void addIndexContents(Map<ModuleElement, Set<PackageElement>> modules, String text,
             String tableSummary, Content body) {
-        if (profiles.getProfileCount() > 0) {
-            HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
-                    ? HtmlTree.NAV()
-                    : new HtmlTree(HtmlTag.DIV);
-            htmlTree.addStyle(HtmlStyle.indexNav);
-            HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            addAllClassesLink(ul);
-            addAllPackagesLink(ul);
-            htmlTree.addContent(ul);
-            body.addContent(htmlTree);
-            addProfilesList(profiles, text, tableSummary, body);
-        }
-    }
-
-    /**
-     * Adds profile packages index contents. Call appropriate methods from
-     * the sub-classes. Adds it to the body HtmlTree
-     *
-     * @param profiles profiles to be documented
-     * @param text string which will be used as the heading
-     * @param tableSummary summary for the table
-     * @param body the document tree to which the index contents will be added
-     * @param profileName the name of the profile being documented
-     */
-    protected void addProfilePackagesIndexContents(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName) {
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
@@ -226,10 +208,33 @@
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         addAllPackagesLink(ul);
-        addAllProfilesLink(ul);
         htmlTree.addContent(ul);
         body.addContent(htmlTree);
-        addProfilePackagesList(profiles, text, tableSummary, body, profileName);
+        addModulesList(modules, text, tableSummary, body);
+    }
+
+    /**
+     * Adds module packages index contents. Call appropriate methods from
+     * the sub-classes. Adds it to the body HtmlTree
+     *
+     * @param text string which will be used as the heading
+     * @param tableSummary summary for the table
+     * @param body the document tree to which the index contents will be added
+     * @param mdle the module being documented
+     */
+    protected void addModulePackagesIndexContents(String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
+                ? HtmlTree.NAV()
+                : new HtmlTree(HtmlTag.DIV);
+        htmlTree.addStyle(HtmlStyle.indexNav);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        addAllClassesLink(ul);
+        addAllPackagesLink(ul);
+        addAllModulesLink(ul);
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+        addModulePackagesList(modules, text, tableSummary, body, mdle);
     }
 
     /**
@@ -259,7 +264,7 @@
     }
 
     /**
-     * Do nothing. This will be overridden in ProfileIndexFrameWriter.
+     * Do nothing. This will be overridden in ModuleIndexFrameWriter.
      *
      * @param div the document tree to which the all classes link will be added
      */
@@ -267,7 +272,7 @@
     }
 
     /**
-     * Do nothing. This will be overridden in ProfileIndexFrameWriter.
+     * Do nothing. This will be overridden in ModuleIndexFrameWriter.
      *
      * @param div the document tree to which the all packages link will be added
      */
@@ -275,10 +280,10 @@
     }
 
     /**
-     * Do nothing. This will be overridden in ProfilePackageIndexFrameWriter.
+     * Do nothing. This will be overridden in ModulePackageIndexFrameWriter.
      *
-     * @param div the document tree to which the all profiles link will be added
+     * @param div the document tree to which the all modules link will be added
      */
-    protected void addAllProfilesLink(Content div) {
+    protected void addAllModulesLink(Content div) {
     }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
index 26061a8..62a1074 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
@@ -160,6 +160,9 @@
             htmlTree.addStyle(HtmlStyle.indexNav);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
             addAllClassesLink(ul);
+            if (configuration.showModules) {
+                addAllModulesLink(ul);
+            }
             htmlTree.addContent(ul);
             body.addContent(htmlTree);
             addPackagesList(packages, text, tableSummary, body);
@@ -199,4 +202,12 @@
      */
     protected void addAllClassesLink(Content div) {
     }
+
+    /**
+     * Do nothing. This will be overridden.
+     *
+     * @param div the document tree to which the all modules link will be added
+     */
+    protected void addAllModulesLink(Content div) {
+    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
index 17efe9c..4137cef 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
@@ -30,6 +30,7 @@
 
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -194,12 +195,22 @@
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
+        ModuleElement mdle = configuration.root.getElementUtils().getModuleOf(typeElement);
+        if (mdle != null && !mdle.isUnnamed()) {
+            Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, moduleLabel);
+            Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
+            moduleNameDiv.addContent(getSpace());
+            moduleNameDiv.addContent(getModuleLink(mdle,
+                    new StringContent(mdle.getQualifiedName().toString())));
+            div.addContent(moduleNameDiv);
+        }
         PackageElement pkg = utils.containingPackage(typeElement);
         if (!pkg.isUnnamed()) {
             Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel);
             Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
             pkgNameDiv.addContent(getSpace());
-            Content pkgNameContent = getPackageLink(pkg, new StringContent(pkg.getQualifiedName()));
+            Content pkgNameContent = getPackageLink(pkg,
+                    new StringContent(utils.getPackageName(pkg)));
             pkgNameDiv.addContent(pkgNameContent);
             div.addContent(pkgNameDiv);
         }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
index 0b7aa5e..64b4b3f 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
@@ -25,6 +25,7 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import java.io.IOException;
 import java.net.*;
 import java.util.*;
 
@@ -33,10 +34,15 @@
 import javax.lang.model.element.TypeElement;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
 
 import com.sun.source.util.DocTreePath;
 import com.sun.tools.doclint.DocLint;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
 
 import jdk.javadoc.doclet.Doclet;
 import jdk.javadoc.doclet.DocletEnvironment;
@@ -49,6 +55,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
 import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 
@@ -507,6 +514,20 @@
         return new ContentBuilder();
     }
 
+    @Override
+    public Location getLocationForPackage(PackageElement pd) {
+        JavaFileManager fm = getFileManager();
+        if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH) && (pd instanceof PackageSymbol)) {
+            try {
+                ModuleSymbol msym = ((PackageSymbol) pd).modle;
+                return fm.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH, msym.name.toString());
+            } catch (IOException e) {
+                throw new DocletAbortException(e);
+            }
+        }
+        return StandardLocation.SOURCE_PATH;
+    }
+
     protected void buildSearchTagIndex() {
         for (SearchIndexItem sii : tagSearchIndex) {
             String tagLabel = sii.getLabel();
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
index 70f4a0f..bfa3060 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
@@ -140,7 +140,7 @@
             packageNameContent.addContent(".*");
             link = getHyperLink(DocLink.fragment(parsedPackageName),
                     packageNameContent, "", "");
-            PackageElement abbrevPkg = utils.elementUtils.getPackageElement(parsedPackageName);
+            PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(pkg);
             printedPackageHeaders.add(abbrevPkg);
         }
         contentListTree.addContent(HtmlTree.LI(link));
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
index b0f8ad9..1c0464e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
@@ -28,9 +28,11 @@
 import java.io.*;
 import java.util.*;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
+import com.sun.javadoc.PackageDoc;
 import jdk.javadoc.doclet.Doclet.Option;
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.doclet.Reporter;
@@ -248,6 +250,7 @@
             } catch (IOException e) {
                 throw new DocletAbortException(e);
             } catch (DocletAbortException de) {
+                de.printStackTrace();
                 throw de;
             } catch (Exception e) {
                 e.printStackTrace();
@@ -256,6 +259,37 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    protected void generateModuleFiles() throws Exception {
+        if (configuration.showModules) {
+            ModuleIndexFrameWriter.generate(configuration);
+            ModuleElement prevModule = null, nextModule;
+            List<ModuleElement> mdles = new ArrayList<>(configuration.modulePackages.keySet());
+            int i = 0;
+            for (ModuleElement mdle : mdles) {
+                ModulePackageIndexFrameWriter.generate(configuration, mdle);
+                nextModule = (i + 1 < mdles.size()) ? mdles.get(i + 1) : null;
+                AbstractBuilder moduleSummaryBuilder =
+                        configuration.getBuilderFactory().getModuleSummaryBuilder(
+                        mdle, prevModule, nextModule);
+                moduleSummaryBuilder.build();
+                prevModule = mdle;
+                i++;
+            }
+        }
+    }
+
+    PackageElement getNamedPackage(List<PackageElement> list, int idx) {
+        if (idx < list.size()) {
+            PackageElement pkg = list.get(idx);
+            if (pkg != null && !pkg.isUnnamed()) {
+                return pkg;
+            }
+        }
+        return null;
+    }
 
     /**
      * {@inheritDoc}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
index 294bc60..71eedc8 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
@@ -35,6 +35,7 @@
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
@@ -351,6 +352,33 @@
         return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
     }
 
+    /**
+     * Get Module Package link, with target frame.
+     *
+     * @param pkg the PackageElement
+     * @param target name of the target frame
+     * @param label tag for the link
+     * @param mdle the module being documented
+     * @return a content for the target module packages link
+     */
+    public Content getTargetModulePackageLink(PackageElement pkg, String target,
+            Content label, ModuleElement mdle) {
+        return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
+                label, "", target);
+    }
+
+    /**
+     * Get Module link, with target frame.
+     *
+     * @param target name of the target frame
+     * @param label tag for the link
+     * @param mdle the module being documented
+     * @return a content for the target module link
+     */
+    public Content getTargetModuleLink(String target, Content label, ModuleElement mdle) {
+        return getHyperLink(pathToRoot.resolve(
+                DocPaths.moduleSummary(mdle)), label, "", target);
+    }
 
     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
             String tableSummary, List<String> tableHeader, Content summaryContentTree) {
@@ -599,6 +627,8 @@
                 fixedNavDiv.addContent(subDiv);
                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
                 tree.addContent(fixedNavDiv);
+                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, getSpace());
+                tree.addContent(paddingDiv);
             } else {
                 subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
                 tree.addContent(subDiv);
@@ -1081,6 +1111,18 @@
         }
     }
 
+    /**
+     * Get Module link.
+     *
+     * @param mdle the module being documented
+     * @param label tag for the link
+     * @return a content for the module link
+     */
+    public Content getModuleLink(ModuleElement mdle, Content label) {
+        return getHyperLink(pathToRoot.resolve(
+                DocPaths.moduleSummary(mdle)), label, "", "");
+    }
+
     public Content interfaceName(TypeElement typeElement, boolean qual) {
         Content name = new StringContent((qual)
                 ? typeElement.getQualifiedName()
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java
similarity index 61%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java
rename to langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java
index 18f45c0..38bd8cc 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -23,20 +23,30 @@
  * questions.
  */
 
-package com.sun.tools.doclets.formats.html;
+package jdk.javadoc.internal.doclets.formats.html;
 
 import java.io.*;
+import java.util.Map;
+import java.util.Set;
 
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-import com.sun.tools.javac.jvm.Profile;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
 
 /**
- * Generate the profile index for the left-hand frame in the generated output.
- * A click on the profile name in this frame will update the page in the top
- * left hand frame with the listing of packages of the clicked profile.
+ * Generate the module index for the left-hand frame in the generated output.
+ * A click on the module name in this frame will update the page in the top
+ * left hand frame with the listing of packages of the clicked module.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
@@ -45,31 +55,31 @@
  *
  * @author Bhavesh Patel
  */
-public class ProfileIndexFrameWriter extends AbstractProfileIndexWriter {
+public class ModuleIndexFrameWriter extends AbstractModuleIndexWriter {
 
     /**
-     * Construct the ProfileIndexFrameWriter object.
+     * Construct the ModuleIndexFrameWriter object.
      *
      * @param configuration the configuration object
-     * @param filename Name of the profile index file to be generated.
+     * @param filename Name of the module index file to be generated.
      */
-    public ProfileIndexFrameWriter(ConfigurationImpl configuration,
+    public ModuleIndexFrameWriter(ConfigurationImpl configuration,
                                    DocPath filename) throws IOException {
         super(configuration, filename);
     }
 
     /**
-     * Generate the profile index file named "profile-overview-frame.html".
+     * Generate the module index file named "module-overview-frame.html".
      * @throws DocletAbortException
      * @param configuration the configuration object
      */
     public static void generate(ConfigurationImpl configuration) {
-        ProfileIndexFrameWriter profilegen;
-        DocPath filename = DocPaths.PROFILE_OVERVIEW_FRAME;
+        ModuleIndexFrameWriter modulegen;
+        DocPath filename = DocPaths.MODULE_OVERVIEW_FRAME;
         try {
-            profilegen = new ProfileIndexFrameWriter(configuration, filename);
-            profilegen.buildProfileIndexFile("doclet.Window_Overview", false);
-            profilegen.close();
+            modulegen = new ModuleIndexFrameWriter(configuration, filename);
+            modulegen.buildModuleIndexFile("doclet.Window_Overview", false);
+            modulegen.close();
         } catch (IOException exc) {
             configuration.standardmessage.error(
                         "doclet.exception_encountered",
@@ -81,40 +91,35 @@
     /**
      * {@inheritDoc}
      */
-    protected void addProfilesList(Profiles profiles, String text,
+    protected void addModulesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
             String tableSummary, Content body) {
-        Content heading = HtmlTree.HEADING(HtmlConstants.PROFILE_HEADING, true,
-                profilesLabel);
+        Content heading = HtmlTree.HEADING(HtmlConstants.MODULE_HEADING, true,
+                modulesLabel);
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
                 ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
                 : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.setTitle(profilesLabel);
-        String profileName;
-        for (int i = 1; i < profiles.getProfileCount(); i++) {
-            profileName = (Profile.lookup(i)).name;
-            // If the profile has valid packages to be documented, add it to the
-            // left-frame generated for profile index.
-            if (configuration.shouldDocumentProfile(profileName))
-                ul.addContent(getProfile(profileName));
+        ul.setTitle(modulesLabel);
+        for (ModuleElement mdle: modules.keySet()) {
+            ul.addContent(getModuleLink(mdle));
         }
         htmlTree.addContent(ul);
         body.addContent(htmlTree);
     }
 
     /**
-     * Returns each profile name as a separate link.
+     * Returns each module name as a separate link.
      *
-     * @param profileName the profile being documented
-     * @return content for the profile link
+     * @param moduleName the module being documented
+     * @return content for the module link
      */
-    protected Content getProfile(String profileName) {
-        Content profileLinkContent;
-        Content profileLabel;
-        profileLabel = new StringContent(profileName);
-        profileLinkContent = getHyperLink(DocPaths.profileFrame(profileName), profileLabel, "",
-                    "packageListFrame");
-        Content li = HtmlTree.LI(profileLinkContent);
+    protected Content getModuleLink(ModuleElement mdle) {
+        Content moduleLinkContent;
+        Content moduleLabel;
+        moduleLabel = new StringContent(mdle.getQualifiedName().toString());
+        moduleLinkContent = getHyperLink(DocPaths.moduleFrame(mdle),
+                moduleLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(moduleLinkContent);
         return li;
     }
 
@@ -173,7 +178,7 @@
         body.addContent(p);
     }
 
-    protected void addProfilePackagesList(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName) {
+    protected void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle) {
     }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java
new file mode 100644
index 0000000..dd87080
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
+
+/**
+ * Generate the module package index for the left-hand frame in the generated output.
+ * A click on the package name in this frame will update the page in the bottom
+ * left hand frame with the listing of contents of the clicked module package.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModulePackageIndexFrameWriter extends AbstractModuleIndexWriter {
+
+    /**
+     * Construct the ModulePackageIndexFrameWriter object.
+     *
+     * @param configuration the configuration object
+     * @param filename Name of the package index file to be generated.
+     */
+    public ModulePackageIndexFrameWriter(ConfigurationImpl configuration,
+                                   DocPath filename) throws IOException {
+        super(configuration, filename);
+    }
+
+    /**
+     * Generate the module package index file.
+     * @throws DocletAbortException
+     * @param configuration the configuration object
+     * @param mdle the module being documented
+     */
+    public static void generate(ConfigurationImpl configuration, ModuleElement mdle) {
+        ModulePackageIndexFrameWriter modpackgen;
+        DocPath filename = DocPaths.moduleFrame(mdle);
+        try {
+            modpackgen = new ModulePackageIndexFrameWriter(configuration, filename);
+            modpackgen.buildModulePackagesIndexFile("doclet.Window_Overview", false, mdle);
+            modpackgen.close();
+        } catch (IOException exc) {
+            configuration.standardmessage.error(
+                        "doclet.exception_encountered",
+                        exc.toString(), filename);
+            throw new DocletAbortException(exc);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+        Content profNameContent = new StringContent(mdle.getQualifiedName().toString());
+        Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true,
+                getTargetModuleLink("classFrame", profNameContent, mdle));
+        heading.addContent(getSpace());
+        heading.addContent(packagesLabel);
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
+                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
+                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setTitle(packagesLabel);
+        List<PackageElement> packages = new ArrayList<>(modules.get(mdle));
+        for (PackageElement pkg : packages) {
+            if ((!(configuration.nodeprecated && utils.isDeprecated(pkg)))) {
+                ul.addContent(getPackage(pkg, mdle));
+            }
+        }
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addModulePackagesList(Set<ModuleElement> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+        Content moduleNameContent = new StringContent(mdle.getQualifiedName().toString());
+        Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true,
+                getTargetModuleLink("classFrame", moduleNameContent, mdle));
+        heading.addContent(getSpace());
+        heading.addContent(packagesLabel);
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
+                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
+                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setTitle(packagesLabel);
+        Set<PackageElement> modulePackages = configuration.modulePackages.get(mdle);
+        for (PackageElement pkg: modulePackages) {
+            if ((!(configuration.nodeprecated && utils.isDeprecated(pkg)))) {
+                ul.addContent(getPackage(pkg, mdle));
+            }
+        }
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+    }
+
+    /**
+     * Returns each package name as a separate link.
+     *
+     * @param pkg PackageElement
+     * @param mdle the module being documented
+     * @return content for the package link
+     */
+    protected Content getPackage(PackageElement pkg, ModuleElement mdle) {
+        Content packageLinkContent;
+        Content pkgLabel;
+        if (!pkg.isUnnamed()) {
+            pkgLabel = getPackageLabel(utils.getPackageName(pkg));
+            packageLinkContent = getHyperLink(pathString(pkg,
+                     DocPaths.PACKAGE_FRAME), pkgLabel, "",
+                    "packageFrame");
+        } else {
+            pkgLabel = new StringContent("<unnamed package>");
+            packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME,
+                    pkgLabel, "", "packageFrame");
+        }
+        Content li = HtmlTree.LI(packageLinkContent);
+        return li;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addNavigationBarHeader(Content body) {
+        Content headerContent;
+        if (configuration.packagesheader.length() > 0) {
+            headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader));
+        } else {
+            headerContent = new RawHtml(replaceDocRootDir(configuration.header));
+        }
+        Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
+                HtmlStyle.bar, headerContent);
+        body.addContent(heading);
+    }
+
+    /**
+     * Do nothing as there is no overview information in this page.
+     */
+    protected void addOverviewHeader(Content body) {
+    }
+
+    protected void addModulesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body) {
+    }
+
+    /**
+     * Adds "All Classes" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all classes link should be added
+     */
+    protected void addAllClassesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
+                allclassesLabel, "", "packageFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * Adds "All Packages" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all packages link should be added
+     */
+    protected void addAllPackagesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
+                allpackagesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * Adds "All Modules" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all modules link should be added
+     */
+    protected void addAllModulesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.MODULE_OVERVIEW_FRAME,
+                allmodulesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addNavigationBarFooter(Content body) {
+        Content p = HtmlTree.P(getSpace());
+        body.addContent(p);
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
new file mode 100644
index 0000000..105cb70
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html;
+
+import java.io.*;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+import com.sun.source.doctree.DocTree;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
+import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+
+/**
+ * Class to generate file for each module contents in the right-hand
+ * frame. This will list all the packages and Class Kinds in the module. A click on any
+ * class-kind will update the frame with the clicked class-kind page. A click on any
+ * package will update the frame with the clicked module package page.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryWriter {
+
+    /**
+     * The prev module name in the alpha-order list.
+     */
+    protected ModuleElement prevModule;
+
+    /**
+     * The next module name in the alpha-order list.
+     */
+    protected ModuleElement nextModule;
+
+    /**
+     * The module being documented.
+     */
+    protected ModuleElement mdle;
+
+    /**
+     * The HTML tree for main tag.
+     */
+    protected HtmlTree mainTree = HtmlTree.MAIN();
+
+    /**
+     * Constructor to construct ModuleWriter object and to generate
+     * "moduleName-summary.html" file.
+     *
+     * @param configuration the configuration of the doclet.
+     * @param module        Module under consideration.
+     * @param prevModule   Previous module in the sorted array.
+     * @param nextModule   Next module in the sorted array.
+     */
+    public ModuleWriterImpl(ConfigurationImpl configuration,
+            ModuleElement mdle, ModuleElement prevModule, ModuleElement nextModule)
+            throws IOException {
+        super(configuration, DocPaths.moduleSummary(mdle));
+        this.prevModule = prevModule;
+        this.nextModule = nextModule;
+        this.mdle = mdle;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getModuleHeader(String heading) {
+        HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString()));
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
+                ? HtmlTree.HEADER()
+                : bodyTree;
+        addTop(htmlTree);
+        addNavLinks(true, htmlTree);
+        if (configuration.allowTag(HtmlTag.HEADER)) {
+            bodyTree.addContent(htmlTree);
+        }
+        HtmlTree div = new HtmlTree(HtmlTag.DIV);
+        div.addStyle(HtmlStyle.header);
+        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
+                HtmlStyle.title, moduleLabel);
+        tHeading.addContent(getSpace());
+        Content moduleHead = new RawHtml(heading);
+        tHeading.addContent(moduleHead);
+        div.addContent(tHeading);
+        if (configuration.allowTag(HtmlTag.MAIN)) {
+            mainTree.addContent(div);
+        } else {
+            bodyTree.addContent(div);
+        }
+        return bodyTree;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getContentHeader() {
+        HtmlTree div = new HtmlTree(HtmlTag.DIV);
+        div.addStyle(HtmlStyle.contentContainer);
+        return div;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getSummaryHeader() {
+        HtmlTree li = new HtmlTree(HtmlTag.LI);
+        li.addStyle(HtmlStyle.blockList);
+        return li;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getSummaryTree(Content summaryContentTree) {
+        HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
+        return ul;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addPackagesSummary(Set<PackageElement> packages, String text,
+            String tableSummary, Content summaryContentTree) {
+        Content table = (configuration.isOutputHtml5())
+                ? HtmlTree.TABLE(HtmlStyle.overviewSummary, getTableCaption(new RawHtml(text)))
+                : HtmlTree.TABLE(HtmlStyle.overviewSummary, tableSummary, getTableCaption(new RawHtml(text)));
+        table.addContent(getSummaryTableHeader(packageTableHeader, "col"));
+        Content tbody = new HtmlTree(HtmlTag.TBODY);
+        addPackagesList(packages, tbody);
+        table.addContent(tbody);
+        summaryContentTree.addContent(table);
+    }
+
+    /**
+     * Adds list of packages in the package summary table. Generate link to each package.
+     *
+     * @param packages Packages to which link is to be generated
+     * @param tbody the documentation tree to which the list will be added
+     */
+    protected void addPackagesList(Set<PackageElement> packages, Content tbody) {
+        boolean altColor = true;
+        for (PackageElement pkg : packages) {
+            if (pkg != null && !pkg.isUnnamed()) {
+                if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
+                    Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
+                    Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent);
+                    HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
+                    tdSummary.addStyle(HtmlStyle.colLast);
+                    addSummaryComment(pkg, tdSummary);
+                    HtmlTree tr = HtmlTree.TR(tdPackage);
+                    tr.addContent(tdSummary);
+                    tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+                    tbody.addContent(tr);
+                }
+            }
+            altColor = !altColor;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addModuleContent(Content contentTree, Content moduleContentTree) {
+        if (configuration.allowTag(HtmlTag.MAIN)) {
+            mainTree.addContent(moduleContentTree);
+            contentTree.addContent(mainTree);
+        } else {
+            contentTree.addContent(moduleContentTree);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addModuleFooter(Content contentTree) {
+        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
+                ? HtmlTree.FOOTER()
+                : contentTree;
+        addNavLinks(false, htmlTree);
+        addBottom(htmlTree);
+        if (configuration.allowTag(HtmlTag.FOOTER)) {
+            contentTree.addContent(htmlTree);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void printDocument(Content contentTree) throws IOException {
+        printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle),
+                true, contentTree);
+    }
+
+    /**
+     * Add the module package deprecation information to the documentation tree.
+     *
+     * @param li the content tree to which the deprecation information will be added
+     * @param pkg the PackageDoc that is added
+     */
+    public void addPackageDeprecationInfo(Content li, PackageElement pkg) {
+        List<? extends DocTree> deprs;
+        if (utils.isDeprecated(pkg)) {
+            deprs = utils.getDeprecatedTrees(pkg);
+            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
+            deprDiv.addStyle(HtmlStyle.deprecatedContent);
+            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
+            deprDiv.addContent(deprPhrase);
+            if (!deprs.isEmpty()) {
+                CommentHelper ch = utils.getCommentHelper(pkg);
+                List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
+                if (!commentTags.isEmpty()) {
+                    addInlineDeprecatedComment(pkg, deprs.get(0), deprDiv);
+                }
+            }
+            li.addContent(deprDiv);
+        }
+    }
+
+    /**
+     * Get "PREV MODULE" link in the navigation bar.
+     *
+     * @return a content tree for the previous link
+     */
+    public Content getNavLinkPrevious() {
+        Content li;
+        if (prevModule == null) {
+            li = HtmlTree.LI(prevmoduleLabel);
+        } else {
+            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
+                    prevModule)), prevmoduleLabel, "", ""));
+        }
+        return li;
+    }
+
+    /**
+     * Get "NEXT MODULE" link in the navigation bar.
+     *
+     * @return a content tree for the next link
+     */
+    public Content getNavLinkNext() {
+        Content li;
+        if (nextModule == null) {
+            li = HtmlTree.LI(nextmoduleLabel);
+        } else {
+            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
+                    nextModule)), nextmoduleLabel, "", ""));
+        }
+        return li;
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java
index 94170a3..e83d4ab 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java
@@ -167,6 +167,19 @@
     }
 
     /**
+     * Adds "All Modules" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the "All Modules" link should be added
+     */
+    protected void addAllModulesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.MODULE_OVERVIEW_FRAME,
+                allmodulesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
      * {@inheritDoc}
      */
     protected void addNavigationBarFooter(Content body) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
index 8689b0f..64d76a0 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.util.*;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
@@ -124,6 +125,15 @@
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
+        ModuleElement mdle = configuration.root.getElementUtils().getModuleOf(packageElement);
+        if (mdle != null && !mdle.isUnnamed()) {
+            Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, moduleLabel);
+            Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
+            moduleNameDiv.addContent(getSpace());
+            moduleNameDiv.addContent(getModuleLink(mdle,
+                    new StringContent(mdle.getQualifiedName().toString())));
+            div.addContent(moduleNameDiv);
+        }
         Content annotationContent = new HtmlTree(HtmlTag.P);
         addAnnotationInfo(packageElement, annotationContent);
         div.addContent(annotationContent);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
index cce4052..7e67fa7 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -38,6 +39,7 @@
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
+import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
@@ -83,6 +85,15 @@
     /**
      * {@inheritDoc}
      */
+    public ModuleSummaryWriter getModuleSummaryWriter(ModuleElement mdle,
+        ModuleElement prevModule, ModuleElement nextModule) throws Exception {
+        return new ModuleWriterImpl(configuration, mdle,
+            prevModule, nextModule);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ClassWriter getClassWriter(TypeElement typeElement, TypeElement prevClass,
             TypeElement nextClass, ClassTree classTree) throws IOException {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java
index b1e03e3..1b7731b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java
@@ -192,6 +192,11 @@
     public static final HtmlTag PACKAGE_HEADING = HtmlTag.H2;
 
     /**
+     * Html tag for the module name heading.
+     */
+    public static final HtmlTag MODULE_HEADING = HtmlTag.H2;
+
+    /**
      * Html tag for the member summary heading.
      */
     public static final HtmlTag SUMMARY_HEADING = HtmlTag.H3;
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
index f55de09..301f86d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
@@ -77,10 +77,12 @@
     memberNameLabel,
     memberNameLink,
     memberSummary,
+    moduleLabelInClass,
     nameValue,
     navBarCell1Rev,
     navList,
     navListSearch,
+    navPadding,
     overrideSpecifyLabel,
     overviewSummary,
     packageHierarchyLabel,
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
index dce9fd7..f3774d2 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
@@ -67,6 +67,11 @@
     protected boolean memberDetailsListPrinted;
 
     /**
+     * Header for table displaying modules and description..
+     */
+    protected final List<String> moduleTableHeader;
+
+    /**
      * Header for tables displaying packages and description..
      */
     protected final List<String> packageTableHeader;
@@ -87,6 +92,8 @@
 
     public final Content packageLabel;
 
+    public final Content moduleLabel;
+
     public final Content useLabel;
 
     public final Content prevLabel;
@@ -117,6 +124,8 @@
 
     public final Content allpackagesLabel;
 
+    public final Content allmodulesLabel;
+
     public final Content indexLabel;
 
     public final Content helpLabel;
@@ -129,8 +138,14 @@
 
     public final Content nextpackageLabel;
 
+    public final Content prevmoduleLabel;
+
+    public final Content nextmoduleLabel;
+
     public final Content packagesLabel;
 
+    public final Content modulesLabel;
+
     public final Content methodDetailsLabel;
 
     public final Content annotationTypeDetailsLabel;
@@ -171,6 +186,9 @@
         writer = DocFile.createFileForOutput(configuration, path).openWriter();
         this.configuration = configuration;
         this.memberDetailsListPrinted = false;
+        moduleTableHeader = Arrays.asList(
+            configuration.getText("doclet.Module"),
+            configuration.getText("doclet.Description"));
         packageTableHeader = new ArrayList<>();
         packageTableHeader.add(configuration.getText("doclet.Package"));
         packageTableHeader.add(configuration.getText("doclet.Description"));
@@ -182,6 +200,7 @@
         overviewLabel = getResource("doclet.Overview");
         defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME);
         packageLabel = getResource("doclet.Package");
+        moduleLabel = getResource("doclet.Module");
         useLabel = getResource("doclet.navClassUse");
         prevLabel = getResource("doclet.Prev");
         nextLabel = getResource("doclet.Next");
@@ -197,13 +216,17 @@
         deprecatedPhrase = getResource("doclet.Deprecated");
         allclassesLabel = getNonBreakResource("doclet.All_Classes");
         allpackagesLabel = getNonBreakResource("doclet.All_Packages");
+        allmodulesLabel = getNonBreakResource("doclet.All_Modules");
         indexLabel = getResource("doclet.Index");
         helpLabel = getResource("doclet.Help");
         seeLabel = getResource("doclet.See");
         descriptionLabel = getResource("doclet.Description");
         prevpackageLabel = getNonBreakResource("doclet.Prev_Package");
         nextpackageLabel = getNonBreakResource("doclet.Next_Package");
+        prevmoduleLabel = getNonBreakResource("doclet.Prev_Module");
+        nextmoduleLabel = getNonBreakResource("doclet.Next_Module");
         packagesLabel = getResource("doclet.Packages");
+        modulesLabel = getResource("doclet.Modules");
         methodDetailsLabel = getResource("doclet.Method_Detail");
         annotationTypeDetailsLabel = getResource("doclet.Annotation_Type_Member_Detail");
         fieldDetailsLabel = getResource("doclet.Field_Detail");
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
index 8e7ac74..6356cbf 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
@@ -4,7 +4,9 @@
 doclet.Window_Overview=Overview List
 doclet.Window_Overview_Summary=Overview
 doclet.Package=Package
+doclet.Module=Module
 doclet.All_Packages=All Packages
+doclet.All_Modules=All Modules
 doclet.Tree=Tree
 doclet.Class_Hierarchy=Class Hierarchy
 doclet.Window_Class_Hierarchy=Class Hierarchy
@@ -17,6 +19,8 @@
 doclet.Next_Class=Next Class
 doclet.Prev_Package=Prev Package
 doclet.Next_Package=Next Package
+doclet.Prev_Module=Prev Module
+doclet.Next_Module=Next Module
 doclet.Prev_Letter=Prev Letter
 doclet.Next_Letter=Next Letter
 doclet.Href_Class_Title=class in {0}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
index e634140..a5ffa28 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
@@ -107,7 +107,6 @@
             return false;
         } catch (DocletAbortException e) {
             Throwable cause = e.getCause();
-            // e.printStackTrace();
             if (cause != null) {
                 if (cause.getLocalizedMessage() != null) {
                     configuration.reporter.print(ERROR, cause.getLocalizedMessage());
@@ -163,6 +162,7 @@
 
         PackageListWriter.generate(configuration);
         generatePackageFiles(classtree);
+        generateModuleFiles();
 
         generateOtherFiles(root, classtree);
         configuration.tagletManager.printReport();
@@ -183,6 +183,12 @@
     }
 
     /**
+     * Generate the module documentation.
+     *
+     */
+    protected abstract void generateModuleFiles() throws Exception;
+
+    /**
      * Generate the package documentation.
      *
      * @param classtree the data structure representing the class tree.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
index 9577631..f16b817 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
@@ -31,9 +31,11 @@
 import java.util.regex.Pattern;
 
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 
 import com.sun.source.util.DocTreePath;
@@ -240,6 +242,17 @@
     public boolean showversion = false;
 
     /**
+     * Sourcepath from where to read the source files. Default is classpath.
+     *
+     */
+    public String sourcepath = "";
+
+    /**
+     * Generate modules documentation if more than one module is present.
+     */
+    public boolean showModules = false;
+
+    /**
      * Don't generate deprecated API information at all, if -nodeprecated
      * option is used. <code>nodepracted</code> is set to true if
      * -nodeprecated option is used. Default is generate deprected API
@@ -336,6 +349,11 @@
     public DocFileFactory docFileFactory;
 
     /**
+     * A sorted set of modules containing the packages.
+     */
+    public Map<ModuleElement, Set<PackageElement>> modulePackages;
+
+    /**
      * Constructor. Constructs the message retriever with resource file.
      */
     public Configuration() {
@@ -365,6 +383,21 @@
         return this.reporter;
     }
 
+    private void initModules() {
+        // Build the modules structure used by the doclet
+        modulePackages = new TreeMap<>(utils.makeModuleComparator());
+        for (PackageElement p: packages) {
+            ModuleElement mdle = root.getElementUtils().getModuleOf(p);
+            if (mdle != null && !mdle.isUnnamed()) {
+                Set<PackageElement> s = modulePackages.get(mdle);
+                if (s == null)
+                    modulePackages.put(mdle, s = new TreeSet<>(utils.makePackageComparator()));
+                s.add(p);
+            }
+        }
+        showModules = (modulePackages.size() > 1);
+    }
+
     private void initPackages() {
         packages = new TreeSet<>(utils.makePackageComparator());
         packages.addAll(utils.getSpecifiedPackages());
@@ -617,12 +650,13 @@
     /**
      * Set the command line options supported by this configuration.
      *
-     * @return
+     * @return true if the options are set successfully
      * @throws DocletAbortException
      */
-    public boolean setOptions() {
+    public boolean setOptions() throws Fault {
         try {
             initPackages();
+            initModules();
             finishOptionSettings0();
             if (!finishOptionSettings())
                 return false;
@@ -1181,4 +1215,6 @@
             this.value2 = value2;
         }
     }
+
+    public abstract Location getLocationForPackage(PackageElement pd);
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java
similarity index 60%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java
rename to langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java
index 5008daf..50a87a6 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -23,14 +23,15 @@
  * questions.
  */
 
-package com.sun.tools.doclets.internal.toolkit;
+package jdk.javadoc.internal.doclets.toolkit;
 
 import java.io.*;
+import java.util.Set;
 
-import com.sun.javadoc.*;
+import javax.lang.model.element.PackageElement;
 
 /**
- * The interface for writing profile summary output.
+ * The interface for writing module summary output.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
@@ -40,20 +41,20 @@
  * @author Bhavesh Patel
  */
 
-public interface ProfileSummaryWriter {
+public interface ModuleSummaryWriter {
 
     /**
      * Get the header for the summary.
      *
-     * @param heading profile name.
+     * @param heading module name.
      * @return the header to be added to the content tree
      */
-    public abstract Content getProfileHeader(String heading);
+    public abstract Content getModuleHeader(String heading);
 
     /**
-     * Get the header for the profile content.
+     * Get the header for the module content.
      *
-     * @return a content tree for the profile content header
+     * @return a content tree for the module content header
      */
     public abstract Content getContentHeader();
 
@@ -73,48 +74,33 @@
     public abstract Content getSummaryTree(Content summaryContentTree);
 
     /**
-     * Get the header for the package summary header.
+     * Adds the table of packages to the documentation tree.
      *
-     * @return a content tree with the package summary header
-     */
-    public abstract Content getPackageSummaryHeader(PackageDoc pkg);
-
-    /**
-     * Get the header for the package summary tree.
-     *
-     * @return a content tree with the package summary
-     */
-    public abstract Content getPackageSummaryTree(Content packageSummaryContentTree);
-
-    /**
-     * Adds the table of classes to the documentation tree.
-     *
-     * @param classes the array of classes to document.
+     * @param packages the set of packages that should be added.
      * @param label the label for this table.
      * @param tableSummary the summary string for the table
-     * @param tableHeader array of table headers
-     * @param packageSummaryContentTree the content tree to which the summaries will be added
+     * @param summaryContentTree the content tree to which the summary will be added
      */
-    public abstract void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content packageSummaryContentTree);
+    public abstract void addPackagesSummary(Set<PackageElement> packages, String label,
+            String tableSummary, Content summaryContentTree);
 
     /**
-     * Adds the profile content tree to the documentation tree.
+     * Adds the module content tree to the documentation tree.
      *
-     * @param contentTree the tree to which the profile content tree will be added
-     * @param profileContentTree the content tree that will be added
+     * @param contentTree the tree to which the module content tree will be added
+     * @param moduleContentTree the content tree that will be added
      */
-    public abstract void addProfileContent(Content contentTree, Content profileContentTree);
+    public abstract void addModuleContent(Content contentTree, Content moduleContentTree);
 
     /**
      * Adds the footer to the documentation tree.
      *
      * @param contentTree the tree to which the footer will be added
      */
-    public abstract void addProfileFooter(Content contentTree);
+    public abstract void addModuleFooter(Content contentTree);
 
     /**
-     * Print the profile summary document.
+     * Print the module summary document.
      *
      * @param contentTree the content tree that will be printed
      */
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
index 83cbac7..569209b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
@@ -38,6 +38,7 @@
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
@@ -59,6 +60,7 @@
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.model.JavacElements;
 import com.sun.tools.javac.model.JavacTypes;
 import com.sun.tools.javac.util.Names;
 
@@ -68,6 +70,7 @@
 
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
+
 import static javax.lang.model.element.ElementKind.*;
 
 /**
@@ -532,4 +535,21 @@
     public JavaFileObject getJavaFileObject(PackageElement pe) {
         return env.pkgToJavaFOMap.get(pe);
     }
+
+    // TODO: we need to eliminate this, as it is hacky.
+    /**
+     * Returns a representation of the package truncated to two levels.
+     * For instance if the given package represents foo.bar.baz will return
+     * a representation of foo.bar
+     * @param pkg the PackageElement
+     * @return an abbreviated PackageElement
+     */
+    public PackageElement getAbbreviatedPackageElement(PackageElement pkg) {
+        String parsedPackageName = utils.parsePackageName(pkg);
+        ModuleElement encl = (ModuleElement) pkg.getEnclosingElement();
+        PackageElement abbrevPkg = encl == null
+                ? utils.elementUtils.getPackageElement(parsedPackageName)
+                : ((JavacElements) utils.elementUtils).getPackageElement(encl, parsedPackageName);
+        return abbrevPkg;
+    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
index dc5441a..a9f400e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
@@ -25,6 +25,7 @@
 
 package jdk.javadoc.internal.doclets.toolkit;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -68,6 +69,19 @@
     throws Exception;
 
     /**
+     * Return the writer for the module summary.
+     *
+     * @param mdle the module being documented.
+     * @param prevModule the previous module that was documented.
+     * @param nextModule the next module being documented.
+     * @return the writer for the module summary.  Return null if this
+     * writer is not supported by the doclet.
+     */
+    public abstract ModuleSummaryWriter getModuleSummaryWriter(
+        ModuleElement mdle, ModuleElement prevModule, ModuleElement nextModule)
+    throws Exception;
+
+    /**
      * Return the writer for a class.
      *
      * @param typeElement the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java
index c7731c1..2b8ccd4 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java
@@ -28,6 +28,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -102,6 +103,20 @@
     }
 
     /**
+     * Return the builder that builds the module summary.
+     *
+     * @param mdle the module being documented.
+     * @param prevModule the previous module being documented.
+     * @param nextModule the next module being documented.
+     * @return the builder that builds the module summary.
+     */
+    public AbstractBuilder getModuleSummaryBuilder(ModuleElement mdle, ModuleElement prevModule,
+            ModuleElement nextModule) throws Exception {
+        return ModuleSummaryBuilder.getInstance(context, mdle,
+            writerFactory.getModuleSummaryWriter(mdle, prevModule, nextModule));
+    }
+
+    /**
      * Return the builder for the class.
      *
      * @param typeElement the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
index 080921e..d0a36f7 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
@@ -200,11 +200,10 @@
      * @param summariesTree the tree to which the package header will be added
      */
     public void buildPackageHeader(XMLNode node, Content summariesTree) {
-        String parsedPackageName = utils.parsePackageName(currentPackage);
-        PackageElement p = utils.elementUtils.getPackageElement(parsedPackageName);
-        if (!printedPackageHeaders.contains(p)) {
+        PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(currentPackage);
+        if (!printedPackageHeaders.contains(abbrevPkg)) {
             writer.addPackageName(currentPackage, summariesTree, first);
-            printedPackageHeaders.add(p);
+            printedPackageHeaders.add(abbrevPkg);
         }
     }
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java
new file mode 100644
index 0000000..d2de20d
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.toolkit.builders;
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+import javax.tools.StandardLocation;
+
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+
+
+/**
+ * Builds the summary for a given module.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModuleSummaryBuilder extends AbstractBuilder {
+    /**
+     * The root element of the module summary XML is {@value}.
+     */
+    public static final String ROOT = "ModuleDoc";
+
+    /**
+     * The module being documented.
+     */
+    private final ModuleElement mdle;
+
+    /**
+     * The doclet specific writer that will output the result.
+     */
+    private final ModuleSummaryWriter moduleWriter;
+
+    /**
+     * The content that will be added to the module summary documentation tree.
+     */
+    private Content contentTree;
+
+    /**
+     * The module package being documented.
+     */
+    private PackageElement pkg;
+
+    /**
+     * Construct a new ModuleSummaryBuilder.
+     *
+     * @param context  the build context.
+     * @param mdle the module being documented.
+     * @param moduleWriter the doclet specific writer that will output the
+     *        result.
+     */
+    private ModuleSummaryBuilder(Context context,
+            ModuleElement mdle, ModuleSummaryWriter moduleWriter) {
+        super(context);
+        this.mdle = mdle;
+        this.moduleWriter = moduleWriter;
+    }
+
+    /**
+     * Construct a new ModuleSummaryBuilder.
+     *
+     * @param context  the build context.
+     * @param mdle the module being documented.
+     * @param moduleWriter the doclet specific writer that will output the
+     *        result.
+     *
+     * @return an instance of a ModuleSummaryBuilder.
+     */
+    public static ModuleSummaryBuilder getInstance(Context context,
+            ModuleElement mdle, ModuleSummaryWriter moduleWriter) {
+        return new ModuleSummaryBuilder(context, mdle, moduleWriter);
+    }
+
+    /**
+     * Build the module summary.
+     */
+    public void build() throws IOException {
+        if (moduleWriter == null) {
+            //Doclet does not support this output.
+            return;
+        }
+        build(layoutParser.parseXML(ROOT), contentTree);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return ROOT;
+    }
+
+    /**
+     * Build the module documentation.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param contentTree the content tree to which the documentation will be added
+     */
+    public void buildModuleDoc(XMLNode node, Content contentTree) throws Exception {
+        contentTree = moduleWriter.getModuleHeader(mdle.getSimpleName().toString());
+        buildChildren(node, contentTree);
+        moduleWriter.addModuleFooter(contentTree);
+        moduleWriter.printDocument(contentTree);
+        moduleWriter.close();
+        // TEMPORARY:
+        // The use of SOURCE_PATH on the next line is temporary. As we transition into the
+        // modules world, this should migrate into using a location for the appropriate module
+        // on the MODULE_SOURCE_PATH, or (in the old doclet) simply deleted.
+        utils.copyDocFiles(configuration, StandardLocation.SOURCE_PATH, DocPaths.moduleSummary(mdle));
+    }
+
+    /**
+     * Build the content for the module doc.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param contentTree the content tree to which the module contents
+     *                    will be added
+     */
+    public void buildContent(XMLNode node, Content contentTree) {
+        Content moduleContentTree = moduleWriter.getContentHeader();
+        buildChildren(node, moduleContentTree);
+        moduleWriter.addModuleContent(contentTree, moduleContentTree);
+    }
+
+    /**
+     * Build the module summary.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param moduleContentTree the module content tree to which the summaries will
+     *                           be added
+     */
+    public void buildSummary(XMLNode node, Content moduleContentTree) {
+        Content summaryContentTree = moduleWriter.getSummaryHeader();
+        buildChildren(node, summaryContentTree);
+        moduleContentTree.addContent(moduleWriter.getSummaryTree(summaryContentTree));
+    }
+
+    /**
+     * Build the module package summary.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param summaryContentTree the content tree to which the summaries will
+     *                           be added
+     */
+    public void buildPackageSummary(XMLNode node, Content summaryContentTree) {
+        Set<PackageElement> packages = configuration.modulePackages.get(mdle);
+        if (!packages.isEmpty()) {
+            String packageTableSummary
+                    = configuration.getText("doclet.Member_Table_Summary",
+                            configuration.getText("doclet.Package_Summary"),
+                            configuration.getText("doclet.packages"));
+            moduleWriter.addPackagesSummary(
+                    packages, configuration.getText("doclet.Package_Summary"),
+                    packageTableSummary, summaryContentTree);
+        }
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml
index 88c998d..62a3183 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='utf-8'?>
 
 <!--
- Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,14 @@
 
 <Doclet>
 
+    <ModuleDoc>
+        <Content>
+            <Summary>
+                <PackageSummary/>
+            </Summary>
+        </Content>
+    </ModuleDoc>
+
     <PackageDoc>
         <Content>
             <Summary>
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
index a4b574d..00ed40b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
@@ -31,6 +31,7 @@
 doclet.Building_Index_For_All_Classes=Building index for all classes...
 doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
 doclet.Packages=Packages
+doclet.Modules=Modules
 doclet.Other_Packages=Other Packages
 doclet.Notice_taglet_registered=Registered Taglet {0} ...
 doclet.Notice_taglet_unseen=Note: Custom tags that were not seen: {0}
@@ -68,6 +69,7 @@
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
 doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
+doclet.Module_Summary=Module Summary
 doclet.Interface_Summary=Interface Summary
 doclet.Annotation_Types_Summary=Annotation Types Summary
 doclet.Enum_Summary=Enum Summary
@@ -90,6 +92,7 @@
 doclet.Classes=Classes
 doclet.Packages=Packages
 doclet.packages=packages
+doclet.modules=modules
 doclet.All_Classes=All Classes
 doclet.All_Superinterfaces=All Superinterfaces:
 doclet.All_Implemented_Interfaces=All Implemented Interfaces:
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
index 4a0e575..eef017b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
@@ -143,6 +143,9 @@
     font-size:11px;
     margin:0;
 }
+.navPadding {
+    padding-top: 100px;
+}
 .fixedNav {
     position:fixed;
     width:100%;
@@ -265,7 +268,6 @@
 .title {
     color:#2c4557;
     margin:10px 0;
-    padding-top:5.4em;
 }
 .subTitle {
     margin:5px 0 0 0;
@@ -610,9 +612,9 @@
     color:#474747;
 }
 .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
-.overrideSpecifyLabel, .packageLabelInClass, .packageHierarchyLabel,
-.paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, .throwsLabel,
-.typeNameLabel, .typeNameLink, .searchTagLink {
+.moduleLabelInClass, .overrideSpecifyLabel, .packageLabelInClass,
+.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel,
+.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink {
     font-weight:bold;
 }
 .deprecationComment, .emphasizedPhrase, .interfaceName {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
index 9cc9dc2..f03b1c4 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
@@ -26,6 +26,7 @@
 package jdk.javadoc.internal.doclets.toolkit.taglets;
 
 import java.io.*;
+import java.lang.reflect.Method;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -231,7 +232,7 @@
      */
     public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) {
         try {
-            ClassLoader tagClassLoader;
+            ClassLoader tagClassLoader = null;
             if (!fileManager.hasLocation(TAGLET_PATH)) {
                 List<File> paths = new ArrayList<>();
                 if (tagletPath != null) {
@@ -245,6 +246,7 @@
             }
             tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
             Class<?> customTagClass = tagClassLoader.loadClass(classname);
+            ensureReadable(customTagClass);
             Object instance = customTagClass.newInstance();
             Taglet newLegacy = new UserTaglet((jdk.javadoc.doclet.taglet.Taglet)instance);
             String tname = newLegacy.getName();
@@ -260,6 +262,27 @@
     }
 
     /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e.toString());
+        }
+    }
+
+    /**
      * Add a new <code>SimpleTaglet</code>.  If this tag already exists
      * and the header passed as an argument is null, move tag to the back of the
      * list. If this tag already exists and the header passed as an argument is
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
index 8eaf210..57956f9 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.toolkit.util;
 
+import javax.lang.model.element.ModuleElement;
+
 /**
  * Standard DocPath objects.
  *
@@ -143,6 +145,19 @@
     /** The name of the file for the package usage info. */
     public static final DocPath PACKAGE_USE = DocPath.create("package-use.html");
 
+    /** The name of the file for the module frame. */
+    public static DocPath moduleFrame(ModuleElement mdle) {
+        return DocPath.create(mdle.getQualifiedName() + "-frame.html");
+    }
+
+    /** The name of the file for the module summary. */
+    public static DocPath moduleSummary(ModuleElement mdle) {
+        return DocPath.create(mdle.getQualifiedName() + "-summary.html");
+    }
+
+    /** The name of the file for the module overview frame. */
+    public static final DocPath MODULE_OVERVIEW_FRAME = DocPath.create("module-overview-frame.html");
+
     /** The name of the sub-package from which resources are read. */
     public static final DocPath RESOURCES = DocPath.create("resources");
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java
index c36f293..d0bac01 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
@@ -109,6 +110,19 @@
     }
 
     /**
+     * Get the module keywords.
+     *
+     * @param mdle the module being documented
+     */
+    public List<String> getMetaKeywordsForModule(ModuleElement mdle) {
+        if (config.keywords) {
+            return Arrays.asList(mdle.getQualifiedName() + " " + "module");
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
      * Get the overview keywords.
      */
     public List<String> getOverviewMetaKeywords(String title, String docTitle) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java
index 004fcb1..6cf91e5 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java
@@ -104,12 +104,12 @@
 
     @Override
     Iterable<DocFile> list(Location location, DocPath path) {
-        if (location != StandardLocation.SOURCE_PATH)
-            throw new IllegalArgumentException();
+        Location l = ((location == StandardLocation.SOURCE_PATH)
+                && !fileManager.hasLocation(StandardLocation.SOURCE_PATH))
+                ? StandardLocation.CLASS_PATH
+                : location;
 
         Set<DocFile> files = new LinkedHashSet<>();
-        Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
         for (Path f: fileManager.getLocationAsPaths(l)) {
             if (Files.isDirectory(f)) {
                 f = f.resolve(path.getPath());
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
index fa2c90f..d2d5d2a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
@@ -41,6 +41,7 @@
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.TypeParameterElement;
@@ -60,6 +61,7 @@
 import javax.lang.model.util.TypeKindVisitor9;
 import javax.lang.model.util.Types;
 import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
 import com.sun.source.doctree.DocCommentTree;
@@ -1539,6 +1541,45 @@
         return secondaryCollator.compare(s1, s2);
     }
 
+    public void copyDocFiles(Configuration configuration, Location locn, DocPath dir) {
+        try {
+            boolean first = true;
+            for (DocFile f : DocFile.list(configuration, locn, dir)) {
+                if (!f.isDirectory()) {
+                    continue;
+                }
+                DocFile srcdir = f;
+                DocFile destdir = DocFile.createFileForOutput(configuration, dir);
+                if (srcdir.isSameFile(destdir)) {
+                    continue;
+                }
+
+                for (DocFile srcfile: srcdir.list()) {
+                    DocFile destfile = destdir.resolve(srcfile.getName());
+                    if (srcfile.isFile()) {
+                        if (destfile.exists() && !first) {
+                            configuration.message.warning("doclet.Copy_Overwrite_warning",
+                                    srcfile.getPath(), destdir.getPath());
+                        } else {
+                            configuration.message.notice(
+                                    "doclet.Copying_File_0_To_Dir_1",
+                                    srcfile.getPath(), destdir.getPath());
+                            destfile.copyFile(srcfile);
+                        }
+                    } else if (srcfile.isDirectory()) {
+                        if (configuration.copydocfilesubdirs
+                                && !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
+                            copyDocFiles(configuration, locn, dir.resolve(srcfile.getName()));
+                        }
+                    }
+                }
+
+                first = false;
+            }
+        } catch (SecurityException | IOException exc) {
+            throw new com.sun.tools.doclets.internal.toolkit.util.DocletAbortException(exc);
+        }
+    }
 
     private static class DocCollator {
         private final Map<String, CollationKey> keys;
@@ -1567,6 +1608,18 @@
     }
 
     /**
+     * Comparator for ModuleElements, simply compares the fully qualified names
+     */
+    public Comparator<Element> makeModuleComparator() {
+        return new Utils.ElementComparator<Element>() {
+            @Override
+            public int compare(Element mod1, Element mod2) {
+                return compareFullyQualifiedNames(mod1, mod2);
+            }
+        };
+    }
+
+    /**
      * Comparator for PackageElements, simply compares the fully qualified names
      */
     public Comparator<Element> makePackageComparator() {
@@ -1942,6 +1995,11 @@
          */
         private String getFullyQualifiedName(Element e) {
             return new SimpleElementVisitor9<String, Void>() {
+                @Override  @DefinedBy(Api.LANGUAGE_MODEL)
+                public String visitModule(ModuleElement e, Void p) {
+                    return e.getQualifiedName().toString();
+                }
+
                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
                 public String visitPackage(PackageElement e, Void p) {
                     return e.getQualifiedName().toString();
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java
index 0be30eb..674187d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java
@@ -50,6 +50,7 @@
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
@@ -65,8 +66,10 @@
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
@@ -164,7 +167,7 @@
         finder = JavadocClassFinder.instance(context);
         enter = JavadocEnter.instance(context);
         names = Names.instance(context);
-        externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable"));
+        externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
         chk = Check.instance(context);
         types = com.sun.tools.javac.code.Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
@@ -199,7 +202,9 @@
      */
     public TypeElement loadClass(String name) {
         try {
-            ClassSymbol c = finder.loadClass(names.fromString(name));
+            Name nameImpl = names.fromString(name);
+            ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+            ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
             return c;
         } catch (CompletionFailure ex) {
             chk.completionError(null, ex);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java
index d546d4a..b62c322 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java
@@ -66,6 +66,7 @@
                                                           JavaFileObject.Kind.HTML);
     private EnumSet<JavaFileObject.Kind> noSource = EnumSet.of(JavaFileObject.Kind.CLASS,
                                                                JavaFileObject.Kind.HTML);
+    private JavacTrees jctrees;
 
     private final JavacTrees trees;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java
index c8250e6..227063a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java
@@ -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
@@ -48,6 +48,7 @@
 import com.sun.tools.javac.code.ClassFinder;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -95,6 +96,7 @@
     /**
      * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
      */
+    @Override
     protected boolean keepComments() {
         return true;
     }
@@ -158,6 +160,7 @@
         Set<String> includedPackages = new LinkedHashSet<>();
 
         try {
+
             StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager
                     ? (StandardJavaFileManager) docenv.fileManager : null;
             Set<String> packageNames = new LinkedHashSet<>();
@@ -165,7 +168,11 @@
             // Parse the files and collect the package names.
             for (String arg: args) {
                 if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
-                    parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    if (new File(arg).getName().equals("module-info.java")) {
+                        docenv.warning("main.file_ignored", arg);
+                    } else {
+                        parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    }
                 } else if (isValidPackageName(arg)) {
                     packageNames.add(arg);
                 } else if (arg.endsWith(".java")) {
@@ -180,10 +187,15 @@
 
             // Parse file objects provide via the DocumentationTool API
             parse(fileObjects, classTrees, true);
+            modules.enter(classTrees.toList(), null);
+
+            syms.unnamedModule.complete(); // TEMP to force reading all named modules
 
             // Build up the complete list of any packages to be documented
-            Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+            Location location =
+                    modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH
+                    : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH
+                    : StandardLocation.CLASS_PATH;
 
             PackageTable t = new PackageTable(docenv.fileManager, location)
                     .packages(packageNames)
@@ -200,6 +212,7 @@
                     docenv.warning("main.no_source_files_for_package", packageName);
                 parse(files, packageTrees, false);
             }
+            modules.enter(packageTrees.toList(), null);
 
             if (messager.nerrors() != 0) {
                 return null;
@@ -208,6 +221,8 @@
             // Enter symbols for all files
             docenv.notice("main.Building_tree");
             javadocEnter.main(classTrees.toList().appendList(packageTrees.toList()));
+
+            enterDone = true;
         } catch (Abort ex) {}
 
         if (messager.nerrors() != 0)
@@ -296,7 +311,7 @@
     /**
      * A table to manage included and excluded packages.
      */
-    static class PackageTable {
+    class PackageTable {
         private final Map<String, Entry> entries = new LinkedHashMap<>();
         private final Set<String> includedPackages = new LinkedHashSet<>();
         private final JavaFileManager fm;
@@ -363,8 +378,11 @@
                 return e.files;
 
             ListBuffer<JavaFileObject> lb = new ListBuffer<>();
-            for (JavaFileObject fo: fm.list(location, packageName, sourceKinds, false)) {
-                String binaryName = fm.inferBinaryName(location, fo);
+            Location packageLocn = getLocation(packageName);
+            if (packageLocn == null)
+                return Collections.emptyList();
+            for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) {
+                String binaryName = fm.inferBinaryName(packageLocn, fo);
                 String simpleName = getSimpleName(binaryName);
                 if (isValidClassName(simpleName)) {
                     lb.append(fo);
@@ -374,6 +392,18 @@
             return lb.toList();
         }
 
+        private Location getLocation(String packageName) throws IOException {
+            if (location == StandardLocation.MODULE_SOURCE_PATH) {
+                // TODO: handle invalid results better.
+                ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
+                if (msym == null) {
+                    return null;
+                }
+                return fm.getModuleLocation(location, msym.name.toString());
+            } else {
+                return location;
+            }
+        }
 
         private Entry getEntry(String name) {
             Entry e = entries.get(name);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
index 4cc5e18..0de7455 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
@@ -29,6 +29,7 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Method;
 import java.nio.file.Path;
 import java.text.BreakIterator;
 import java.util.ArrayList;
@@ -39,7 +40,9 @@
 import java.util.Locale;
 import java.util.Objects;
 import java.util.Set;
+
 import static javax.tools.DocumentationTool.Location.*;
+
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
@@ -249,6 +252,7 @@
             try {
                 doclet = (Doclet) docletClass.newInstance();
             } catch (InstantiationException | IllegalAccessException exc) {
+                exc.printStackTrace();
                 if (!apiMode) {
                     error("main.could_not_instantiate_class", docletClass);
                     messager.exit();
@@ -306,6 +310,27 @@
     }
 
     /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
      * Main program - internal
      */
     private boolean parseAndExecute(List<String> argList,
@@ -490,7 +515,9 @@
                     return null; // keep compiler happy
                 }
                 try {
-                    return cl.loadClass(userDocletName);
+                    Class<?> klass = cl.loadClass(userDocletName);
+                    ensureReadable(klass);
+                    return klass;
                 } catch (ClassNotFoundException cnfe) {
                     panic("main.doclet_class_not_found", userDocletName);
                     return null; // keep compiler happy
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java
index 9b0a8ae..7f8d2f0 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,48 @@
         }
     },
 
+    MODULESOURCEPATH("-modulesourcepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULESOURCEPATH, arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.UPGRADEMODULEPATH, arg);
+        }
+    },
+
+    SYSTEM("-system", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SYSTEM, arg);
+        }
+    },
+
+    MODULEPATH("-modulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULEPATH, arg);
+        }
+    },
+
+    ADDMODS("-addmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    LIMITMODS("-limitmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
     ENCODING("-encoding", true) {
         @Override
         public void process(Helper helper, String arg) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties
index 519385d..1bebe48 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties
@@ -86,6 +86,7 @@
 main.illegal_locale_name=Locale not available: {0}
 main.malformed_locale_name=Malformed locale name: {0}
 main.file_not_found=File not found: "{0}"
+main.file_ignored=File ignored: "{0}" (not yet supported)
 main.illegal_class_name=Illegal class name: "{0}"
 main.illegal_package_name=Illegal package name: "{0}"
 main.release.bootclasspath.conflict=option {0} cannot be used together with -release
diff --git a/langtools/src/jdk.javadoc/share/classes/module-info.java b/langtools/src/jdk.javadoc/share/classes/module-info.java
new file mode 100644
index 0000000..c548ec9
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/module-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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
+ * 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.javadoc {
+    requires public java.compiler;
+    requires public jdk.compiler;
+    requires java.xml;
+
+    exports com.sun.javadoc;
+    exports com.sun.tools.doclets;
+    exports com.sun.tools.javadoc;
+    exports jdk.javadoc.doclet;
+    exports jdk.javadoc.doclet.taglet;
+
+    provides javax.tools.DocumentationTool
+        with jdk.javadoc.internal.api.JavadocTool;
+}
+
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java
index 051a325..5e9b685 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -56,7 +56,8 @@
     public static final int ACC_SYNTHETIC     = 0x1000; // class, inner, field, method
     public static final int ACC_ANNOTATION    = 0x2000; // class, inner
     public static final int ACC_ENUM          = 0x4000; // class, inner, field
-    public static final int ACC_MANDATED      = 0x8000; // class, inner, field, method
+    public static final int ACC_MANDATED      = 0x8000; //                          method parameter
+    public static final int ACC_MODULE        = 0x8000; // class
 
     public static enum Kind { Class, InnerClass, Field, Method}
 
@@ -86,7 +87,7 @@
 
     private static final int[] classFlags = {
         ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT,
-        ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
+        ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE
     };
 
     public Set<String> getClassModifiers() {
@@ -247,8 +248,8 @@
             return "ACC_ANNOTATION";
         case ACC_ENUM:
             return "ACC_ENUM";
-        case ACC_MANDATED:
-            return "ACC_MANDATED";
+        case 0x8000:
+            return (t == Kind.Class ? "ACC_MODULE" : "ACC_MANDATED");
         default:
             return null;
         }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java
index ce5ec70..fed0bed 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -42,16 +42,20 @@
     public static final String BootstrapMethods         = "BootstrapMethods";
     public static final String CharacterRangeTable      = "CharacterRangeTable";
     public static final String Code                     = "Code";
+    public static final String ConcealedPackages        = "ConcealedPackages";
     public static final String ConstantValue            = "ConstantValue";
     public static final String CompilationID            = "CompilationID";
     public static final String Deprecated               = "Deprecated";
     public static final String EnclosingMethod          = "EnclosingMethod";
     public static final String Exceptions               = "Exceptions";
+    public static final String Hashes                   = "Hashes";
     public static final String InnerClasses             = "InnerClasses";
     public static final String LineNumberTable          = "LineNumberTable";
     public static final String LocalVariableTable       = "LocalVariableTable";
     public static final String LocalVariableTypeTable   = "LocalVariableTypeTable";
+    public static final String MainClass                = "MainClass";
     public static final String MethodParameters         = "MethodParameters";
+    public static final String Module                   = "Module";
     public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
     public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
     public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@@ -65,6 +69,8 @@
     public static final String StackMap                 = "StackMap";
     public static final String StackMapTable            = "StackMapTable";
     public static final String Synthetic                = "Synthetic";
+    public static final String TargetPlatform           = "TargetPlatform";
+    public static final String Version                  = "Version";
 
     public static class Factory {
         public Factory() {
@@ -109,15 +115,19 @@
             standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class);
             standardAttributes.put(Code,              Code_attribute.class);
             standardAttributes.put(CompilationID,     CompilationID_attribute.class);
+            standardAttributes.put(ConcealedPackages, ConcealedPackages_attribute.class);
             standardAttributes.put(ConstantValue,     ConstantValue_attribute.class);
             standardAttributes.put(Deprecated,        Deprecated_attribute.class);
             standardAttributes.put(EnclosingMethod,   EnclosingMethod_attribute.class);
             standardAttributes.put(Exceptions,        Exceptions_attribute.class);
+            standardAttributes.put(Hashes,            Hashes_attribute.class);
             standardAttributes.put(InnerClasses,      InnerClasses_attribute.class);
             standardAttributes.put(LineNumberTable,   LineNumberTable_attribute.class);
             standardAttributes.put(LocalVariableTable, LocalVariableTable_attribute.class);
             standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class);
+            standardAttributes.put(MainClass,         MainClass_attribute.class);
             standardAttributes.put(MethodParameters,  MethodParameters_attribute.class);
+            standardAttributes.put(Module,            Module_attribute.class);
             standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
             standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
             standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
@@ -131,6 +141,8 @@
             standardAttributes.put(StackMap,          StackMap_attribute.class);
             standardAttributes.put(StackMapTable,     StackMapTable_attribute.class);
             standardAttributes.put(Synthetic,         Synthetic_attribute.class);
+            standardAttributes.put(TargetPlatform,    TargetPlatform_attribute.class);
+            standardAttributes.put(Version,           Version_attribute.class);
         }
 
         private Map<String,Class<? extends Attribute>> standardAttributes;
@@ -166,15 +178,19 @@
         R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p);
         R visitCode(Code_attribute attr, P p);
         R visitCompilationID(CompilationID_attribute attr, P p);
+        R visitConcealedPackages(ConcealedPackages_attribute attr, P p);
         R visitConstantValue(ConstantValue_attribute attr, P p);
         R visitDeprecated(Deprecated_attribute attr, P p);
         R visitEnclosingMethod(EnclosingMethod_attribute attr, P p);
         R visitExceptions(Exceptions_attribute attr, P p);
+        R visitHashes(Hashes_attribute attr, P p);
         R visitInnerClasses(InnerClasses_attribute attr, P p);
         R visitLineNumberTable(LineNumberTable_attribute attr, P p);
         R visitLocalVariableTable(LocalVariableTable_attribute attr, P p);
         R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p);
+        R visitMainClass(MainClass_attribute attr, P p);
         R visitMethodParameters(MethodParameters_attribute attr, P p);
+        R visitModule(Module_attribute attr, P p);
         R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
         R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
         R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
@@ -188,5 +204,7 @@
         R visitStackMap(StackMap_attribute attr, P p);
         R visitStackMapTable(StackMapTable_attribute attr, P p);
         R visitSynthetic(Synthetic_attribute attr, P p);
+        R visitTargetPlatform(TargetPlatform_attribute attr, P p);
+        R visitVersion(Version_attribute attr, P p);
     }
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
index 903931d..b4fad8a 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -221,7 +221,7 @@
             }
         }
 
-        private DataOutputStream d;
+        private final DataOutputStream d;
     }
 
     /**
@@ -234,73 +234,87 @@
             return info.accept(this, out);
         }
 
+        @Override
         public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {
             out.writeShort(info.name_index);
             return 1;
         }
 
+        @Override
         public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {
             out.writeDouble(info.value);
             return 2;
         }
 
+        @Override
         public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {
             writeRef(info, out);
             return 1;
         }
 
+        @Override
         public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {
             out.writeFloat(info.value);
             return 1;
         }
 
+        @Override
         public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {
             out.writeInt(info.value);
             return 1;
         }
 
+        @Override
         public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {
             writeRef(info, out);
             return 1;
         }
 
+        @Override
         public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassOutputStream out) {
             out.writeShort(info.bootstrap_method_attr_index);
             out.writeShort(info.name_and_type_index);
             return 1;
         }
 
+        @Override
         public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
             out.writeLong(info.value);
             return 2;
         }
 
+        @Override
         public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {
             out.writeShort(info.name_index);
             out.writeShort(info.type_index);
             return 1;
         }
 
+        @Override
         public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, ClassOutputStream out) {
             out.writeByte(info.reference_kind.tag);
             out.writeShort(info.reference_index);
             return 1;
         }
 
+        @Override
         public Integer visitMethodType(CONSTANT_MethodType_info info, ClassOutputStream out) {
             out.writeShort(info.descriptor_index);
             return 1;
         }
 
+        @Override
         public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
             return writeRef(info, out);
         }
 
+        @Override
         public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {
             out.writeShort(info.string_index);
             return 1;
         }
 
+        @Override
         public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {
             out.writeUTF(info.value);
             return 1;
@@ -336,16 +350,19 @@
         protected ClassOutputStream sharedOut = new ClassOutputStream();
         protected AnnotationWriter annotationWriter = new AnnotationWriter();
 
+        @Override
         public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {
             out.write(attr.info, 0, attr.info.length);
             return null;
         }
 
+        @Override
         public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.default_value, out);
             return null;
         }
 
+        @Override
         public Void visitBootstrapMethods(BootstrapMethods_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.bootstrap_method_specifiers.length);
             for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : attr.bootstrap_method_specifiers) {
@@ -359,6 +376,7 @@
             return null;
         }
 
+        @Override
         public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.character_range_table.length);
             for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
@@ -374,6 +392,7 @@
             out.writeShort(entry.flags);
         }
 
+        @Override
         public Void visitCode(Code_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.max_stack);
             out.writeShort(attr.max_locals);
@@ -393,26 +412,39 @@
             out.writeShort(exception_data.catch_type);
         }
 
+        @Override
         public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.compilationID_index);
             return null;
         }
 
+        @Override
+        public Void visitConcealedPackages(ConcealedPackages_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.packages_count);
+            for (int i: attr.packages_index)
+                out.writeShort(i);
+            return null;
+        }
+
+        @Override
         public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.constantvalue_index);
             return null;
         }
 
+        @Override
         public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {
             return null;
         }
 
+        @Override
         public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.class_index);
             out.writeShort(attr.method_index);
             return null;
         }
 
+        @Override
         public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.exception_index_table.length);
             for (int i: attr.exception_index_table)
@@ -420,6 +452,7 @@
             return null;
         }
 
+        @Override
         public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.classes.length);
             for (InnerClasses_attribute.Info info: attr.classes)
@@ -427,6 +460,17 @@
             return null;
         }
 
+        @Override
+        public Void visitHashes(Hashes_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.algorithm_index);
+            out.writeShort(attr.hashes_table.length);
+            for (Hashes_attribute.Entry e: attr.hashes_table) {
+                out.writeShort(e.requires_index);
+                out.writeShort(e.hash_index);
+            }
+            return null;
+        }
+
         protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {
             out.writeShort(info.inner_class_info_index);
             out.writeShort(info.outer_class_info_index);
@@ -434,6 +478,7 @@
             writeAccessFlags(info.inner_class_access_flags, out);
         }
 
+        @Override
         public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.line_number_table.length);
             for (LineNumberTable_attribute.Entry e: attr.line_number_table)
@@ -446,6 +491,7 @@
             out.writeShort(entry.line_number);
         }
 
+        @Override
         public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.local_variable_table.length);
             for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)
@@ -461,6 +507,7 @@
             out.writeShort(entry.index);
         }
 
+        @Override
         public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.local_variable_table.length);
             for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)
@@ -476,6 +523,7 @@
             out.writeShort(entry.index);
         }
 
+        @Override
         public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
             out.writeByte(attr.method_parameter_table.length);
             for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
@@ -485,26 +533,62 @@
             return null;
         }
 
+        @Override
+        public Void visitMainClass(MainClass_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.main_class_index);
+            return null;
+        }
+
+        @Override
+        public Void visitModule(Module_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.requires.length);
+            for (Module_attribute.RequiresEntry e: attr.requires) {
+                out.writeShort(e.requires_index);
+                out.writeShort(e.requires_flags);
+            }
+            out.writeShort(attr.exports.length);
+            for (Module_attribute.ExportsEntry e: attr.exports) {
+                out.writeShort(e.exports_index);
+                out.writeShort(e.exports_to_index.length);
+                for (int index: e.exports_to_index)
+                    out.writeShort(index);
+            }
+            out.writeShort(attr.uses_index.length);
+            for (int index: attr.uses_index)
+                out.writeShort(index);
+            out.writeShort(attr.provides.length);
+            for (Module_attribute.ProvidesEntry e: attr.provides) {
+                out.writeShort(e.provides_index);
+                out.writeShort(e.with_index);
+            }
+            return null;
+        }
+
+        @Override
         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
             out.writeByte(attr.parameter_annotations.length);
             for (Annotation[] annos: attr.parameter_annotations)
@@ -512,6 +596,7 @@
             return null;
         }
 
+        @Override
         public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
             out.writeByte(attr.parameter_annotations.length);
             for (Annotation[] annos: attr.parameter_annotations)
@@ -519,26 +604,31 @@
             return null;
         }
 
+        @Override
         public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.signature_index);
             return null;
         }
 
+        @Override
         public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
             out.write(attr.debug_extension, 0, attr.debug_extension.length);
             return null;
         }
 
+        @Override
         public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.sourcefile_index);
             return null;
         }
 
+        @Override
         public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.sourceID_index);
             return null;
         }
 
+        @Override
         public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
             if (stackMapWriter == null)
                 stackMapWriter = new StackMapTableWriter();
@@ -549,6 +639,7 @@
             return null;
         }
 
+        @Override
         public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
             if (stackMapWriter == null)
                 stackMapWriter = new StackMapTableWriter();
@@ -559,14 +650,29 @@
             return null;
         }
 
+        @Override
         public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
             return null;
         }
 
+        @Override
+        public Void visitTargetPlatform(TargetPlatform_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.os_name_index);
+            out.writeShort(attr.os_arch_index);
+            out.writeShort(attr.os_version_index);
+            return null;
+        }
+
         protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
             sharedOut.writeShort(flags.flags);
         }
 
+        @Override
+        public Void visitVersion(Version_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.version_index);
+            return null;
+        }
+
         protected StackMapTableWriter stackMapWriter;
     }
 
@@ -581,31 +687,37 @@
             frame.accept(this, out);
         }
 
+        @Override
         public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
             writeVerificationTypeInfo(frame.stack[0], out);
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             writeVerificationTypeInfo(frame.stack[0], out);
             return null;
         }
 
+        @Override
         public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             return null;
         }
 
+        @Override
         public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             return null;
         }
 
+        @Override
         public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             for (verification_type_info l: frame.locals)
@@ -613,6 +725,7 @@
             return null;
         }
 
+        @Override
         public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             out.writeShort(frame.locals.length);
@@ -692,27 +805,32 @@
             ev.accept(this, out);
         }
 
+        @Override
         public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.const_value_index);
             return null;
         }
 
+        @Override
         public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.type_name_index);
             out.writeShort(ev.const_name_index);
             return null;
         }
 
+        @Override
         public Void visitClass(Class_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.class_info_index);
             return null;
         }
 
+        @Override
         public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
             write(ev.annotation_value, out);
             return null;
         }
 
+        @Override
         public Void visitArray(Array_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.num_values);
             for (element_value v: ev.values)
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java
new file mode 100644
index 0000000..dc56d7b
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class ConcealedPackages_attribute extends Attribute {
+    ConcealedPackages_attribute(ClassReader cr, int name_index, int length)
+            throws IOException {
+        super(name_index, length);
+        packages_count = cr.readUnsignedShort();
+        packages_index = new int[packages_count];
+        for (int i = 0; i < packages_count; i++)
+            packages_index[i] = cr.readUnsignedShort();
+    }
+
+    public ConcealedPackages_attribute(ConstantPool constant_pool,
+                                       int[] packages_index)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.ConcealedPackages),
+             packages_index);
+    }
+
+    public ConcealedPackages_attribute(int name_index,
+                                       int[] packages_index) {
+        super(name_index, 2 + packages_index.length * 2);
+        this.packages_count = packages_index.length;
+        this.packages_index = packages_index;
+    }
+
+    public String getPackage(int index, ConstantPool constant_pool) throws ConstantPoolException {
+        int package_index = packages_index[index];
+        return constant_pool.getUTF8Value(package_index);
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitConcealedPackages(this, data);
+    }
+
+    public final int packages_count;
+    public final int[] packages_index;
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java
new file mode 100644
index 0000000..a248ebc
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Hashes_attribute extends Attribute {
+    Hashes_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        algorithm_index = cr.readUnsignedShort();
+        hashes_table_length = cr.readUnsignedShort();
+        hashes_table = new Entry[hashes_table_length];
+        for (int i = 0; i < hashes_table_length; i++)
+            hashes_table[i] = new Entry(cr);
+    }
+
+    public Hashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.Hashes), algorithm_index, hashes_table);
+    }
+
+    public Hashes_attribute(int name_index, int algorithm_index, Entry[] hashes_table) {
+        super(name_index, 4 + hashes_table.length * Entry.length());
+        this.algorithm_index = algorithm_index;
+        this.hashes_table_length = hashes_table.length;
+        this.hashes_table = hashes_table;
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitHashes(this, data);
+    }
+
+    public final int algorithm_index;
+    public final int hashes_table_length;
+    public final Entry[] hashes_table;
+
+    public static class Entry {
+        Entry(ClassReader cr) throws IOException {
+            requires_index = cr.readUnsignedShort();
+            hash_index = cr.readUnsignedShort();
+        }
+
+        public static int length() {
+            return 4;
+        }
+
+        public final int requires_index;
+        public final int hash_index;
+    }
+
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java
new file mode 100644
index 0000000..ccd4554
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class MainClass_attribute extends Attribute {
+    MainClass_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        main_class_index = cr.readUnsignedShort();
+    }
+
+    public MainClass_attribute(ConstantPool constant_pool, int mainClass_index)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.Version), mainClass_index);
+    }
+
+    public MainClass_attribute(int name_index, int mainClass_index) {
+        super(name_index, 2);
+        this.main_class_index = mainClass_index;
+    }
+
+    public String getMainClassName(ConstantPool constant_pool) throws ConstantPoolException {
+        return constant_pool.getClassInfo(main_class_index).getName();
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitMainClass(this, data);
+    }
+
+    public final int main_class_index;
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java
new file mode 100644
index 0000000..b20729f
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See Jigsaw.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Module_attribute extends Attribute {
+    public static final int ACC_PUBLIC    =   0x20;
+    public static final int ACC_SYNTHETIC = 0x1000;
+    public static final int ACC_MANDATED  = 0x8000;
+
+    Module_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        requires_count = cr.readUnsignedShort();
+        requires = new RequiresEntry[requires_count];
+        for (int i = 0; i < requires_count; i++)
+            requires[i] = new RequiresEntry(cr);
+        exports_count = cr.readUnsignedShort();
+        exports = new ExportsEntry[exports_count];
+        for (int i = 0; i < exports_count; i++)
+            exports[i] = new ExportsEntry(cr);
+        uses_count = cr.readUnsignedShort();
+        uses_index = new int[uses_count];
+        for (int i = 0; i < uses_count; i++)
+            uses_index[i] = cr.readUnsignedShort();
+        provides_count = cr.readUnsignedShort();
+        provides = new ProvidesEntry[provides_count];
+        for (int i = 0; i < provides_count; i++)
+            provides[i] = new ProvidesEntry(cr);
+    }
+
+    public Module_attribute(int name_index,
+            RequiresEntry[] requires,
+            ExportsEntry[] exports,
+            int[] uses,
+            ProvidesEntry[] provides) {
+        super(name_index, 2);
+        requires_count = requires.length;
+        this.requires = requires;
+        exports_count = exports.length;
+        this.exports = exports;
+        uses_count = uses.length;
+        this.uses_index = uses;
+        provides_count = provides.length;
+        this.provides = provides;
+
+    }
+
+    public String getUses(int index, ConstantPool constant_pool) throws ConstantPoolException {
+        int i = uses_index[index];
+        return constant_pool.getClassInfo(i).getName();
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitModule(this, data);
+    }
+
+    public final int requires_count;
+    public final RequiresEntry[] requires;
+    public final int exports_count;
+    public final ExportsEntry[] exports;
+    public final int uses_count;
+    public final int[] uses_index;
+    public final int provides_count;
+    public final ProvidesEntry[] provides;
+
+    public static class RequiresEntry {
+        RequiresEntry(ClassReader cr) throws IOException {
+            requires_index = cr.readUnsignedShort();
+            requires_flags = cr.readUnsignedShort();
+        }
+
+        public RequiresEntry(int index, int flags) {
+            this.requires_index = index;
+            this.requires_flags = flags;
+        }
+
+        public String getRequires(ConstantPool constant_pool) throws ConstantPoolException {
+            return constant_pool.getUTF8Value(requires_index);
+        }
+
+        public static final int length = 4;
+
+        public final int requires_index;
+        public final int requires_flags;
+    }
+
+    public static class ExportsEntry {
+        ExportsEntry(ClassReader cr) throws IOException {
+            exports_index = cr.readUnsignedShort();
+            exports_to_count = cr.readUnsignedShort();
+            exports_to_index = new int[exports_to_count];
+            for (int i = 0; i < exports_to_count; i++)
+                exports_to_index[i] = cr.readUnsignedShort();
+        }
+
+        public ExportsEntry(int index, int[] to) {
+            this.exports_index = index;
+            this.exports_to_count = to.length;
+            this.exports_to_index = to;
+        }
+
+        public int length() {
+            return 4 + 2 * exports_to_index.length;
+        }
+
+        public final int exports_index;
+        public final int exports_to_count;
+        public final int[] exports_to_index;
+    }
+
+    public static class ProvidesEntry {
+        ProvidesEntry(ClassReader cr) throws IOException {
+            provides_index = cr.readUnsignedShort();
+            with_index = cr.readUnsignedShort();
+        }
+
+        public ProvidesEntry(int provides, int with) {
+            this.provides_index = provides;
+            this.with_index = with;
+        }
+
+        public static final int length = 4;
+
+        public final int provides_index;
+        public final int with_index;
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java
new file mode 100644
index 0000000..ad469a5
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java
@@ -0,0 +1,54 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class TargetPlatform_attribute extends Attribute {
+    TargetPlatform_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        os_name_index = cr.readUnsignedShort();
+        os_arch_index = cr.readUnsignedShort();
+        os_version_index = cr.readUnsignedShort();
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitTargetPlatform(this, data);
+    }
+
+    public final int os_name_index;
+    public final int os_arch_index;
+    public final int os_version_index;
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java
new file mode 100644
index 0000000..ed6b749
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Version_attribute extends Attribute {
+    Version_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        version_index = cr.readUnsignedShort();
+    }
+
+    public Version_attribute(ConstantPool constant_pool, int version_index)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.Version), version_index);
+    }
+
+    public Version_attribute(int name_index, int version_index) {
+        super(name_index, 2);
+        this.version_index = version_index;
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitVersion(this, data);
+    }
+
+    public final int version_index;
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java
index 9bd961b..562d419 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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,16 +25,16 @@
 
 package com.sun.tools.javap;
 
-import java.util.Formatter;
-
 import com.sun.tools.classfile.AccessFlags;
 import com.sun.tools.classfile.AnnotationDefault_attribute;
 import com.sun.tools.classfile.Attribute;
 import com.sun.tools.classfile.Attributes;
 import com.sun.tools.classfile.BootstrapMethods_attribute;
 import com.sun.tools.classfile.CharacterRangeTable_attribute;
+import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry;
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.CompilationID_attribute;
+import com.sun.tools.classfile.ConcealedPackages_attribute;
 import com.sun.tools.classfile.ConstantPool;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.ConstantValue_attribute;
@@ -42,11 +42,15 @@
 import com.sun.tools.classfile.Deprecated_attribute;
 import com.sun.tools.classfile.EnclosingMethod_attribute;
 import com.sun.tools.classfile.Exceptions_attribute;
+import com.sun.tools.classfile.Hashes_attribute;
 import com.sun.tools.classfile.InnerClasses_attribute;
+import com.sun.tools.classfile.InnerClasses_attribute.Info;
 import com.sun.tools.classfile.LineNumberTable_attribute;
 import com.sun.tools.classfile.LocalVariableTable_attribute;
 import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
+import com.sun.tools.classfile.MainClass_attribute;
 import com.sun.tools.classfile.MethodParameters_attribute;
+import com.sun.tools.classfile.Module_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
@@ -60,6 +64,8 @@
 import com.sun.tools.classfile.StackMapTable_attribute;
 import com.sun.tools.classfile.StackMap_attribute;
 import com.sun.tools.classfile.Synthetic_attribute;
+import com.sun.tools.classfile.TargetPlatform_attribute;
+import com.sun.tools.classfile.Version_attribute;
 
 import static com.sun.tools.classfile.AccessFlags.*;
 
@@ -114,6 +120,7 @@
         }
     }
 
+    @Override
     public Void visitDefault(DefaultAttribute attr, Void ignore) {
         if (attr.reason != null) {
             report(attr.reason);
@@ -150,6 +157,7 @@
         return null;
     }
 
+    @Override
     public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) {
         println("AnnotationDefault:");
         indent(+1);
@@ -159,6 +167,7 @@
         return null;
     }
 
+    @Override
     public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) {
         println(Attribute.BootstrapMethods + ":");
         for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) {
@@ -178,11 +187,11 @@
         return null;
     }
 
+    @Override
     public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) {
         println("CharacterRangeTable:");
         indent(+1);
-        for (int i = 0; i < attr.character_range_table.length; i++) {
-            CharacterRangeTable_attribute.Entry e = attr.character_range_table[i];
+        for (Entry e : attr.character_range_table) {
             print(String.format("    %2d, %2d, %6x, %6x, %4x",
                     e.start_pc, e.end_pc,
                     e.character_range_start, e.character_range_end,
@@ -216,16 +225,40 @@
         return null;
     }
 
+    @Override
     public Void visitCode(Code_attribute attr, Void ignore) {
         codeWriter.write(attr, constant_pool);
         return null;
     }
 
+    @Override
     public Void visitCompilationID(CompilationID_attribute attr, Void ignore) {
         constantWriter.write(attr.compilationID_index);
         return null;
     }
 
+    private String getJavaPackage(ConcealedPackages_attribute attr, int index) {
+        try {
+            return getJavaName(attr.getPackage(index, constant_pool));
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    @Override
+    public Void visitConcealedPackages(ConcealedPackages_attribute attr, Void ignore) {
+        println("ConcealedPackages: ");
+        indent(+1);
+        for (int i = 0; i < attr.packages_count; i++) {
+            print("#" + attr.packages_index[i]);
+            tab();
+            println("// " + getJavaPackage(attr, i));
+        }
+        indent(-1);
+        return null;
+    }
+
+    @Override
     public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) {
         print("ConstantValue: ");
         constantWriter.write(attr.constantvalue_index);
@@ -233,11 +266,13 @@
         return null;
     }
 
+    @Override
     public Void visitDeprecated(Deprecated_attribute attr, Void ignore) {
         println("Deprecated: true");
         return null;
     }
 
+    @Override
     public Void visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore) {
         print("EnclosingMethod: #" + attr.class_index + ".#" + attr.method_index);
         tab();
@@ -264,6 +299,7 @@
         }
     }
 
+    @Override
     public Void visitExceptions(Exceptions_attribute attr, Void ignore) {
         println("Exceptions:");
         indent(+1);
@@ -286,10 +322,50 @@
         }
     }
 
+    @Override
+    public Void visitHashes(Hashes_attribute attr, Void ignore) {
+        println("Hashes:");
+        indent(+1);
+        print("algorithm #" + attr.algorithm_index);
+        tab();
+        println("// " + getAlgorithm(attr));
+        for (Hashes_attribute.Entry e : attr.hashes_table) {
+            print("#" + e.requires_index + ", #" + e.hash_index);
+            tab();
+            println("// " + getRequires(e) + ": " + getHash(e));
+        }
+        indent(-1);
+        return null;
+    }
+
+    private String getAlgorithm(Hashes_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.algorithm_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getRequires(Hashes_attribute.Entry entry) {
+        try {
+            return constant_pool.getUTF8Value(entry.requires_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getHash(Hashes_attribute.Entry entry) {
+        try {
+            return constant_pool.getUTF8Value(entry.hash_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    @Override
     public Void visitInnerClasses(InnerClasses_attribute attr, Void ignore) {
         boolean first = true;
-        for (int i = 0 ; i < attr.classes.length; i++) {
-            InnerClasses_attribute.Info info = attr.classes[i];
+        for (Info info : attr.classes) {
             //access
             AccessFlags access_flags = info.inner_class_access_flags;
             if (options.checkAccess(access_flags)) {
@@ -338,6 +414,7 @@
         indent(+1);
     }
 
+    @Override
     public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) {
         println("LineNumberTable:");
         indent(+1);
@@ -348,6 +425,7 @@
         return null;
     }
 
+    @Override
     public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) {
         println("LocalVariableTable:");
         indent(+1);
@@ -362,6 +440,7 @@
         return null;
     }
 
+    @Override
     public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) {
         println("LocalVariableTypeTable:");
         indent(+1);
@@ -376,8 +455,26 @@
         return null;
     }
 
+    @Override
+    public Void visitMainClass(MainClass_attribute attr, Void ignore) {
+        print("MainClass: #" + attr.main_class_index);
+        tab();
+        print("// " + getJavaClassName(attr));
+        println();
+        return null;
+    }
+
+    private String getJavaClassName(MainClass_attribute a) {
+        try {
+            return getJavaName(a.getMainClassName(constant_pool));
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
     private static final String format = "%-31s%s";
 
+    @Override
     public Void visitMethodParameters(MethodParameters_attribute attr,
                                       Void ignore) {
 
@@ -400,6 +497,82 @@
         return null;
     }
 
+    @Override
+    public Void visitModule(Module_attribute attr, Void ignore) {
+        println("Module:");
+        indent(+1);
+        printRequiresTable(attr);
+        printExportsTable(attr);
+        printUsesTable(attr);
+        printProvidesTable(attr);
+        indent(-1);
+        return null;
+    }
+
+    protected void printRequiresTable(Module_attribute attr) {
+        Module_attribute.RequiresEntry[] entries = attr.requires;
+        println(entries.length + "\t// " + "requires");
+        indent(+1);
+        for (Module_attribute.RequiresEntry e: entries) {
+            print("#" + e.requires_index + "," +
+                    String.format("%x", e.requires_flags)+ "\t// requires");
+            if ((e.requires_flags & Module_attribute.ACC_PUBLIC) != 0)
+                print(" public");
+            if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0)
+                print(" synthetic");
+            if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0)
+                print(" mandated");
+            println(" " + constantWriter.stringValue(e.requires_index));
+        }
+        indent(-1);
+    }
+
+    protected void printExportsTable(Module_attribute attr) {
+        Module_attribute.ExportsEntry[] entries = attr.exports;
+        println(entries.length + "\t// " + "exports");
+        indent(+1);
+        for (Module_attribute.ExportsEntry e: entries) {
+            print("#" + e.exports_index + "\t// exports");
+            print(" " + constantWriter.stringValue(e.exports_index));
+            if (e.exports_to_index.length == 0) {
+                println();
+            } else {
+                println(" to ... " + e.exports_to_index.length);
+                indent(+1);
+                for (int to: e.exports_to_index) {
+                    println("#" + to + "\t// ... to " + constantWriter.stringValue(to));
+                }
+                indent(-1);
+            }
+        }
+        indent(-1);
+    }
+
+    protected void printUsesTable(Module_attribute attr) {
+        int[] entries = attr.uses_index;
+        println(entries.length + "\t// " + "uses services");
+        indent(+1);
+        for (int e: entries) {
+            println("#" + e + "\t// uses " + constantWriter.stringValue(e));
+        }
+        indent(-1);
+    }
+
+    protected void printProvidesTable(Module_attribute attr) {
+        Module_attribute.ProvidesEntry[] entries = attr.provides;
+        println(entries.length + "\t// " + "provides services");
+        indent(+1);
+        for (Module_attribute.ProvidesEntry e: entries) {
+            print("#" + e.provides_index + ",#" +
+                    e.with_index + "\t// provides ");
+            print(constantWriter.stringValue(e.provides_index));
+            print (" with ");
+            println(constantWriter.stringValue(e.with_index));
+        }
+        indent(-1);
+    }
+
+    @Override
     public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleAnnotations:");
         indent(+1);
@@ -412,6 +585,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleAnnotations:");
         indent(+1);
@@ -424,6 +598,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleTypeAnnotations:");
         indent(+1);
@@ -436,6 +611,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleTypeAnnotations:");
         indent(+1);
@@ -448,6 +624,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleParameterAnnotations:");
         indent(+1);
@@ -465,6 +642,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleParameterAnnotations:");
         indent(+1);
@@ -482,6 +660,7 @@
         return null;
     }
 
+    @Override
     public Void visitSignature(Signature_attribute attr, Void ignore) {
         print("Signature: #" + attr.signature_index);
         tab();
@@ -497,6 +676,7 @@
         }
     }
 
+    @Override
     public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) {
         println("SourceDebugExtension:");
         indent(+1);
@@ -507,6 +687,7 @@
         return null;
     }
 
+    @Override
     public Void visitSourceFile(SourceFile_attribute attr, Void ignore) {
         println("SourceFile: \"" + getSourceFile(attr) + "\"");
         return null;
@@ -520,11 +701,13 @@
         }
     }
 
+    @Override
     public Void visitSourceID(SourceID_attribute attr, Void ignore) {
         constantWriter.write(attr.sourceID_index);
         return null;
     }
 
+    @Override
     public Void visitStackMap(StackMap_attribute attr, Void ignore) {
         println("StackMap: number_of_entries = " + attr.number_of_entries);
         indent(+1);
@@ -536,6 +719,7 @@
         return null;
     }
 
+    @Override
     public Void visitStackMapTable(StackMapTable_attribute attr, Void ignore) {
         println("StackMapTable: number_of_entries = " + attr.number_of_entries);
         indent(+1);
@@ -553,11 +737,13 @@
             frame.accept(this, null);
         }
 
+        @Override
         public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) {
             printHeader(frame, "/* same */");
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) {
             printHeader(frame, "/* same_locals_1_stack_item */");
             indent(+1);
@@ -566,6 +752,7 @@
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) {
             printHeader(frame, "/* same_locals_1_stack_item_frame_extended */");
             indent(+1);
@@ -575,6 +762,7 @@
             return null;
         }
 
+        @Override
         public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) {
             printHeader(frame, "/* chop */");
             indent(+1);
@@ -583,6 +771,7 @@
             return null;
         }
 
+        @Override
         public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) {
             printHeader(frame, "/* same_frame_extended */");
             indent(+1);
@@ -591,6 +780,7 @@
             return null;
         }
 
+        @Override
         public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) {
             printHeader(frame, "/* append */");
             indent(+1);
@@ -600,6 +790,7 @@
             return null;
         }
 
+        @Override
         public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) {
             if (frame instanceof StackMap_attribute.stack_map_frame) {
                 printHeader(frame, "offset = " + frame.offset_delta);
@@ -678,11 +869,80 @@
         }
     }
 
+    @Override
     public Void visitSynthetic(Synthetic_attribute attr, Void ignore) {
         println("Synthetic: true");
         return null;
     }
 
+    @Override
+    public Void visitTargetPlatform(TargetPlatform_attribute attr, Void ignore) {
+        println("TargetPlatform:");
+        indent(+1);
+        print("os_name: #" + attr.os_name_index);
+        if (attr.os_name_index != 0) {
+            tab();
+            print("// " + getOSName(attr));
+        }
+        println();
+        print("os_arch: #" + attr.os_arch_index);
+        if (attr.os_arch_index != 0) {
+            tab();
+            print("// " + getOSArch(attr));
+        }
+        println();
+        print("os_version: #" + attr.os_version_index);
+        if (attr.os_version_index != 0) {
+            tab();
+            print("// " + getOSVersion(attr));
+        }
+        println();
+        indent(-1);
+        return null;
+    }
+
+    private String getOSName(TargetPlatform_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.os_name_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getOSArch(TargetPlatform_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.os_arch_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getOSVersion(TargetPlatform_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.os_version_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    @Override
+    public Void visitVersion(Version_attribute attr, Void ignore) {
+        print("Version: #" + attr.version_index);
+        indent(+1);
+        tab();
+        println("// " + getVersion(attr));
+        indent(-1);
+        return null;
+    }
+
+    private String getVersion(Version_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.version_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
     static String getJavaName(String name) {
         return name.replace('/', '.');
     }
@@ -702,10 +962,10 @@
         return StringUtils.toUpperCase(s);
     }
 
-    private AnnotationWriter annotationWriter;
-    private CodeWriter codeWriter;
-    private ConstantWriter constantWriter;
-    private Options options;
+    private final AnnotationWriter annotationWriter;
+    private final CodeWriter codeWriter;
+    private final ConstantWriter constantWriter;
+    private final Options options;
 
     private ConstantPool constant_pool;
     private Object owner;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java
index a483775..1df09a1 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -44,6 +44,7 @@
 import com.sun.tools.classfile.Exceptions_attribute;
 import com.sun.tools.classfile.Field;
 import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.Module_attribute;
 import com.sun.tools.classfile.Signature;
 import com.sun.tools.classfile.Signature_attribute;
 import com.sun.tools.classfile.SourceFile_attribute;
@@ -161,12 +162,17 @@
 
         writeModifiers(flags.getClassModifiers());
 
-        if (classFile.isClass())
-            print("class ");
-        else if (classFile.isInterface())
-            print("interface ");
+        if (classFile.access_flags.is(AccessFlags.ACC_MODULE) && name.endsWith(".module-info")) {
+            print("module ");
+            print(name.replace(".module-info", ""));
+        } else {
+            if (classFile.isClass())
+                print("class ");
+            else if (classFile.isInterface())
+                print("interface ");
 
-        print(name);
+            print(name);
+        }
 
         Signature_attribute sigAttr = getSignature(cf.attributes);
         if (sigAttr == null) {
@@ -213,6 +219,9 @@
 
         println("{");
         indent(+1);
+        if (flags.is(AccessFlags.ACC_MODULE) && !options.verbose) {
+            writeDirectives();
+        }
         writeFields();
         writeMethods();
         indent(-1);
@@ -538,6 +547,79 @@
         }
     }
 
+    void writeDirectives() {
+        Attribute attr = classFile.attributes.get(Attribute.Module);
+        if (!(attr instanceof Module_attribute))
+            return;
+
+        Module_attribute m = (Module_attribute) attr;
+        for (Module_attribute.RequiresEntry entry: m.requires) {
+            print("requires");
+            if ((entry.requires_flags & Module_attribute.ACC_PUBLIC) != 0)
+                print(" public");
+            print(" ");
+            print(getUTF8Value(entry.requires_index).replace('/', '.'));
+            println(";");
+        }
+
+        for (Module_attribute.ExportsEntry entry: m.exports) {
+            print("exports ");
+            print(getUTF8Value(entry.exports_index).replace('/', '.'));
+            boolean first = true;
+            for (int i: entry.exports_to_index) {
+                String mname;
+                try {
+                    mname = classFile.constant_pool.getUTF8Value(i).replace('/', '.');
+                } catch (ConstantPoolException e) {
+                    mname = report(e);
+                }
+                if (first) {
+                    println(" to");
+                    indent(+1);
+                    first = false;
+                } else {
+                    println(",");
+                }
+                print(mname);
+            }
+            println(";");
+            if (!first)
+                indent(-1);
+        }
+
+        for (int entry: m.uses_index) {
+            print("uses ");
+            print(getClassName(entry).replace('/', '.'));
+            println(";");
+        }
+
+        for (Module_attribute.ProvidesEntry entry: m.provides) {
+            print("provides ");
+            print(getClassName(entry.provides_index).replace('/', '.'));
+            println(" with");
+            indent(+1);
+            print(getClassName(entry.with_index).replace('/', '.'));
+            println(";");
+            indent(-1);
+        }
+    }
+
+    String getUTF8Value(int index) {
+        try {
+            return classFile.constant_pool.getUTF8Value(index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    String getClassName(int index) {
+        try {
+            return classFile.constant_pool.getClassInfo(index).getName();
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
     void writeList(String prefix, Collection<?> items, String suffix) {
         print(prefix);
         String sep = "";
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
index 0cfa5d0..c63caa2 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -55,12 +55,14 @@
 import java.util.MissingResourceException;
 import java.util.Objects;
 import java.util.ResourceBundle;
+import java.util.Set;
 
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.NestingKind;
 import javax.tools.Diagnostic;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
@@ -301,6 +303,13 @@
                 } catch (NumberFormatException e) {
                 }
             }
+        },
+
+        new Option(true, "-m") {
+            @Override
+            void process(JavapTask task, String opt, String arg) throws BadArgs {
+                task.options.moduleName = arg;
+            }
         }
 
     };
@@ -558,6 +567,19 @@
         SourceWriter sourceWriter = SourceWriter.instance(context);
         sourceWriter.setFileManager(fileManager);
 
+        if (options.moduleName != null) {
+            try {
+                moduleLocation = findModule(options.moduleName);
+                if (moduleLocation == null) {
+                    reportError("err.cant.find.module", options.moduleName);
+                    return EXIT_ERROR;
+                }
+            } catch (IOException e) {
+                reportError("err.cant.find.module.ex", options.moduleName, e);
+                return EXIT_ERROR;
+            }
+        }
+
         int result = EXIT_OK;
 
         for (String className: classes) {
@@ -866,15 +888,44 @@
     private JavaFileObject getClassFileObject(String className) throws IOException {
         try {
             JavaFileObject fo;
-            fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
-            if (fo == null)
-                fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+            if (moduleLocation != null) {
+                fo = fileManager.getJavaFileForInput(moduleLocation, className, JavaFileObject.Kind.CLASS);
+            } else {
+                fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+                if (fo == null)
+                    fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+            }
             return fo;
         } catch (IllegalArgumentException e) {
             return null;
         }
     }
 
+    private Location findModule(String moduleName) throws IOException {
+        Location[] locns = {
+            StandardLocation.UPGRADE_MODULE_PATH,
+            StandardLocation.SYSTEM_MODULES,
+            StandardLocation.MODULE_PATH
+        };
+        for (Location segment: locns) {
+            for (Set<Location> set: fileManager.listModuleLocations(segment)) {
+                Location result = null;
+                for (Location l: set) {
+                    String name = fileManager.inferModuleName(l);
+                    if (name.equals(moduleName)) {
+                        if (result == null)
+                            result = l;
+                        else
+                            throw new IOException("multiple definitions found for " + moduleName);
+                    }
+                }
+                if (result != null)
+                    return result;
+            }
+        }
+        return null;
+    }
+
     private void showHelp() {
         printLines(getMessage("main.usage", progname));
         for (Option o: recognizedOptions) {
@@ -883,7 +934,9 @@
                 continue;
             printLines(getMessage("main.opt." + name));
         }
-        String[] fmOptions = { "-classpath", "-cp", "-bootclasspath" };
+        String[] fmOptions = {
+            "-classpath", "-cp", "-bootclasspath",
+            "-upgrademodulepath", "-system", "-modulepath" };
         for (String o: fmOptions) {
             if (fileManager.isSupportedOption(o) == -1)
                 continue;
@@ -1031,6 +1084,7 @@
     PrintWriter log;
     DiagnosticListener<? super JavaFileObject> diagnosticListener;
     List<String> classes;
+    Location moduleLocation;
     Options options;
     //ResourceBundle bundle;
     Locale task_locale;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java
index 3723fc3..3a31155 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -88,4 +88,5 @@
     public boolean showInnerClasses;
     public int indentWidth = 2;   // #spaces per indentWidth level; must be > 0
     public int tabColumn = 40;    // column number for comments; must be > 0
+    public String moduleName;
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties
index ec87869..fb8d19b 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties
@@ -19,6 +19,8 @@
 err.source.file.not.found=source file not found
 err.bad.innerclasses.attribute=bad InnerClasses attribute for {0}
 err.nomem=Insufficient memory. To increase memory use -J-Xmx option.
+err.cant.find.module=Cannot find module {0}
+err.cant.find.module.ex=Problem finding module {0}: {1}
 
 main.usage.summary=\
 Usage: {0} <options> <classes>\n\
@@ -78,6 +80,15 @@
 main.opt.bootclasspath=\
 \  -bootclasspath <path>    Override location of bootstrap class files
 
+main.opt.upgrademodulepath=\
+\  -upgrademodulepath <path>    Specify where to find upgradeable modules
+
+main.opt.system=\
+\  -system <jdk>            Specify where to find system modules
+
+main.opt.modulepath=\
+\  -modulepath <path>       Specify where to find application modules
+
 main.opt.constants=\
 \  -constants               Show final constants
 
@@ -85,3 +96,6 @@
 main.opt.sysinfo=\
 \  -sysinfo                 Show system info (path, size, date, MD5 hash)\n\
 \                           of class being processed
+
+main.opt.m=\
+\  -m <module-name>         Specify module containing classes to be disassembled
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
index 88ee11b..1228622 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
@@ -26,9 +26,13 @@
 package com.sun.tools.jdeps;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -63,9 +67,9 @@
 
     protected final Type type;
     protected final Filter filter;
-    protected final Map<Archive, ArchiveDeps> results = new HashMap<>();
-    protected final Map<Location, Archive> map = new HashMap<>();
-    private static final Archive NOT_FOUND
+    protected final Map<Archive, Dependences> results = new HashMap<>();
+    protected final Map<Location, Archive> locationToArchive = new HashMap<>();
+    static final Archive NOT_FOUND
         = new Archive(JdepsTask.getMessage("artifact.not.found"));
 
     /**
@@ -82,29 +86,31 @@
     /**
      * Performs the dependency analysis on the given archives.
      */
-    public boolean run(List<Archive> archives) {
+    public boolean run(Stream<? extends Archive> archives) {
+        return run(archives.collect(Collectors.toList()));
+    }
+
+    /**
+     * Performs the dependency analysis on the given archives.
+     */
+    public boolean run(Iterable<? extends Archive> archives) {
         // build a map from Location to Archive
         buildLocationArchiveMap(archives);
 
         // traverse and analyze all dependencies
         for (Archive archive : archives) {
-            ArchiveDeps deps = new ArchiveDeps(archive, type);
+            Dependences deps = new Dependences(archive, type);
             archive.visitDependences(deps);
             results.put(archive, deps);
         }
         return true;
     }
 
-    protected void buildLocationArchiveMap(List<Archive> archives) {
+    protected void buildLocationArchiveMap(Iterable<? extends Archive> archives) {
         // build a map from Location to Archive
         for (Archive archive: archives) {
-            for (Location l: archive.getClasses()) {
-                if (!map.containsKey(l)) {
-                    map.put(l, archive);
-                } else {
-                    // duplicated class warning?
-                }
-            }
+            archive.getClasses()
+                   .forEach(l -> locationToArchive.putIfAbsent(l, archive));
         }
     }
 
@@ -116,12 +122,23 @@
     }
 
     public Set<String> dependences(Archive source) {
-        ArchiveDeps result = results.get(source);
+        if (!results.containsKey(source)) {
+            return Collections.emptySet();
+        }
+        Dependences result = results.get(source);
         return result.dependencies().stream()
                      .map(Dep::target)
                      .collect(Collectors.toSet());
     }
 
+    public Stream<Archive> requires(Archive source) {
+        if (!results.containsKey(source)) {
+            return Stream.empty();
+        }
+        Dependences result = results.get(source);
+        return result.requires().stream().filter(a -> !a.isEmpty());
+    }
+
     public interface Visitor {
         /**
          * Visits a recorded dependency from origin to target which can be
@@ -138,7 +155,7 @@
      */
     public void visitDependences(Archive source, Visitor v, Type level) {
         if (level == Type.SUMMARY) {
-            final ArchiveDeps result = results.get(source);
+            final Dependences result = results.get(source);
             final Set<Archive> reqs = result.requires();
             Stream<Archive> stream = reqs.stream();
             if (reqs.isEmpty()) {
@@ -152,19 +169,21 @@
                   .forEach(archive -> {
                       Profile profile = result.getTargetProfile(archive);
                       v.visitDependence(source.getName(), source,
-                                        profile != null ? profile.profileName() : archive.getName(), archive);
+                                        profile != null ? profile.profileName()
+                                                        : archive.getName(), archive);
                   });
         } else {
-            ArchiveDeps result = results.get(source);
+            Dependences result = results.get(source);
             if (level != type) {
                 // requesting different level of analysis
-                result = new ArchiveDeps(source, level);
+                result = new Dependences(source, level);
                 source.visitDependences(result);
             }
             result.dependencies().stream()
                   .sorted(Comparator.comparing(Dep::origin)
                                     .thenComparing(Dep::target))
-                  .forEach(d -> v.visitDependence(d.origin(), d.originArchive(), d.target(), d.targetArchive()));
+                  .forEach(d -> v.visitDependence(d.origin(), d.originArchive(),
+                                                  d.target(), d.targetArchive()));
         }
     }
 
@@ -173,16 +192,16 @@
     }
 
     /**
-     * ArchiveDeps contains the dependencies for an Archive that can have one or
+     * Dependences contains the dependencies for an Archive that can have one or
      * more classes.
      */
-    class ArchiveDeps implements Archive.Visitor {
+    class Dependences implements Archive.Visitor {
         protected final Archive archive;
         protected final Set<Archive> requires;
         protected final Set<Dep> deps;
         protected final Type level;
         private Profile profile;
-        ArchiveDeps(Archive archive, Type level) {
+        Dependences(Archive archive, Type level) {
             this.archive = archive;
             this.deps = new HashSet<>();
             this.requires = new HashSet<>();
@@ -198,7 +217,7 @@
         }
 
         Profile getTargetProfile(Archive target) {
-            if (target instanceof Module) {
+            if (target.getModule().isJDK()) {
                 return Profile.getProfile((Module) target);
             } else {
                 return null;
@@ -206,11 +225,10 @@
         }
 
         Archive findArchive(Location t) {
-            Archive target = archive.getClasses().contains(t) ? archive : map.get(t);
-            if (target == null) {
-                map.put(t, target = NOT_FOUND);
-            }
-            return target;
+            if (archive.getClasses().contains(t))
+                return archive;
+
+            return locationToArchive.computeIfAbsent(t, _k -> NOT_FOUND);
         }
 
         // return classname or package name depedning on the level
@@ -232,7 +250,7 @@
                     requires.add(targetArchive);
                 }
             }
-            if (targetArchive instanceof Module) {
+            if (targetArchive.getModule().isNamed()) {
                 Profile p = Profile.getProfile(t.getPackageName());
                 if (profile == null || (p != null && p.compareTo(profile) > 0)) {
                     profile = p;
@@ -315,12 +333,10 @@
 
         @Override
         public int hashCode() {
-            int hash = 7;
-            hash = 67*hash + Objects.hashCode(this.origin)
-                           + Objects.hashCode(this.originArchive)
-                           + Objects.hashCode(this.target)
-                           + Objects.hashCode(this.targetArchive);
-            return hash;
+            return Objects.hash(this.origin,
+                                this.originArchive,
+                                this.target,
+                                this.targetArchive);
         }
 
         public String toString() {
@@ -329,124 +345,4 @@
                     target, targetArchive.getName());
         }
     }
-
-    static Analyzer getExportedAPIsAnalyzer() {
-        return new ModuleAccessAnalyzer(ModuleAccessAnalyzer.reexportsFilter, true);
-    }
-
-    static Analyzer getModuleAccessAnalyzer() {
-        return new ModuleAccessAnalyzer(ModuleAccessAnalyzer.accessCheckFilter, false);
-    }
-
-    private static class ModuleAccessAnalyzer extends Analyzer {
-        private final boolean apionly;
-        ModuleAccessAnalyzer(Filter filter, boolean apionly) {
-            super(Type.VERBOSE, filter);
-            this.apionly = apionly;
-        }
-        /**
-         * Verify module access
-         */
-        public boolean run(List<Archive> archives) {
-            // build a map from Location to Archive
-            buildLocationArchiveMap(archives);
-
-            // traverse and analyze all dependencies
-            int count = 0;
-            for (Archive archive : archives) {
-                ArchiveDeps checker = new ArchiveDeps(archive, type);
-                archive.visitDependences(checker);
-                count += checker.dependencies().size();
-                // output if any error
-                Module m = (Module)archive;
-                printDependences(System.err, m, checker.dependencies());
-                results.put(archive, checker);
-            }
-            return count == 0;
-        }
-
-        private void printDependences(PrintStream out, Module m, Set<Dep> deps) {
-            if (deps.isEmpty())
-                return;
-
-            String msg = apionly ? "API reference:" : "inaccessible reference:";
-            deps.stream().sorted(Comparator.comparing(Dep::origin)
-                                           .thenComparing(Dep::target))
-                .forEach(d -> out.format("%s %s (%s) -> %s (%s)%n", msg,
-                                         d.origin(), d.originArchive().getName(),
-                                         d.target(), d.targetArchive().getName()));
-            if (apionly) {
-                out.format("Dependences missing re-exports=\"true\" attribute:%n");
-                deps.stream()
-                        .map(Dep::targetArchive)
-                        .map(Archive::getName)
-                        .distinct()
-                        .sorted()
-                        .forEach(d -> out.format("  %s -> %s%n", m.name(), d));
-            }
-        }
-
-        private static Module findModule(Archive archive) {
-            if (Module.class.isInstance(archive)) {
-                return (Module) archive;
-            } else {
-                return null;
-            }
-        }
-
-        // returns true if target is accessible by origin
-        private static boolean canAccess(Location o, Archive originArchive, Location t, Archive targetArchive) {
-            Module origin = findModule(originArchive);
-            Module target = findModule(targetArchive);
-
-            if (targetArchive == Analyzer.NOT_FOUND) {
-                return false;
-            }
-
-            // unnamed module
-            // ## should check public type?
-            if (target == null)
-                return true;
-
-            // module-private
-            if (origin == target)
-                return true;
-
-            return target.isAccessibleTo(t.getClassName(), origin);
-        }
-
-        static final Filter accessCheckFilter = new Filter() {
-            @Override
-            public boolean accepts(Location o, Archive originArchive, Location t, Archive targetArchive) {
-                return !canAccess(o, originArchive, t, targetArchive);
-            }
-        };
-
-        static final Filter reexportsFilter = new Filter() {
-            @Override
-            public boolean accepts(Location o, Archive originArchive, Location t, Archive targetArchive) {
-                Module origin = findModule(originArchive);
-                Module target = findModule(targetArchive);
-                if (!origin.isExportedPackage(o.getPackageName())) {
-                    // filter non-exported classes
-                    return false;
-                }
-
-                boolean accessible = canAccess(o, originArchive, t, targetArchive);
-                if (!accessible)
-                    return true;
-
-                String mn = target.name();
-                // skip checking re-exports for java.base
-                if (origin == target || "java.base".equals(mn))
-                    return false;
-
-                assert origin.requires().containsKey(mn);  // otherwise, should not be accessible
-                if (origin.requires().get(mn)) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
index e6a18f5..90e4890 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
@@ -25,14 +25,17 @@
 
 package com.sun.tools.jdeps;
 
-import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.Dependency.Location;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -48,20 +51,24 @@
         }
     }
 
+    private final URI location;
     private final Path path;
     private final String filename;
     private final ClassFileReader reader;
+
     protected Map<Location, Set<Location>> deps = new ConcurrentHashMap<>();
 
     protected Archive(String name) {
-        this(name, null);
+        this(name, null, null);
     }
-    protected Archive(String name, ClassFileReader reader) {
-        this.path = null;
+    protected Archive(String name, URI location, ClassFileReader reader) {
+        this.location = location;
+        this.path = location != null ? Paths.get(location) : null;
         this.filename = name;
         this.reader = reader;
     }
     protected Archive(Path p, ClassFileReader reader) {
+        this.location = null;
         this.path = p;
         this.filename = path.getFileName().toString();
         this.reader = reader;
@@ -75,6 +82,10 @@
         return filename;
     }
 
+    public Module getModule() {
+        return Module.UNNAMED_MODULE;
+    }
+
     public void addClass(Location origin) {
         deps.computeIfAbsent(origin, _k -> new HashSet<>());
     }
@@ -95,6 +106,9 @@
         }
     }
 
+    /**
+     * Tests if any class has been parsed.
+     */
     public boolean isEmpty() {
         return getClasses().isEmpty();
     }
@@ -103,6 +117,22 @@
         return path != null ? path.toString() : filename;
     }
 
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.filename, this.path);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof Archive) {
+            Archive other = (Archive)o;
+            if (path == other.path || isSameLocation(this, other))
+                return true;
+        }
+        return false;
+    }
+
+    @Override
     public String toString() {
         return filename;
     }
@@ -111,6 +141,29 @@
         return path;
     }
 
+    public static boolean isSameLocation(Archive archive, Archive other) {
+        if (archive.path == null || other.path == null)
+            return false;
+
+        if (archive.location != null && other.location != null &&
+                archive.location.equals(other.location)) {
+            return true;
+        }
+
+        if (archive.isJrt() || other.isJrt()) {
+            return false;
+        }
+
+        try {
+            return Files.isSameFile(archive.path, other.path);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private boolean isJrt() {
+        return location != null && location.getScheme().equals("jrt");
+    }
     interface Visitor {
         void visit(Location origin, Location target);
     }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
index f849b32..aa2e6ff 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
@@ -28,22 +28,26 @@
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.Dependencies.ClassFileError;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
-import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * ClassFileReader reads ClassFile(s) of a given path that can be
@@ -74,8 +78,19 @@
         return new JarFileReader(path, jf);
     }
 
+    /**
+     * Returns a ClassFileReader instance of a given FileSystem and path.
+     *
+     * This method is used for reading classes from jrtfs.
+     */
+    public static ClassFileReader newInstance(FileSystem fs, Path path) throws IOException {
+        return new DirectoryReader(fs, path);
+    }
+
     protected final Path path;
     protected final String baseFileName;
+    protected Set<String> entries; // binary names
+
     protected final List<String> skippedEntries = new ArrayList<>();
     protected ClassFileReader(Path path) {
         this.path = path;
@@ -93,6 +108,18 @@
     }
 
     /**
+     * Returns all entries in this archive.
+     */
+    public Set<String> entries() {
+        Set<String> es = this.entries;
+        if (es == null) {
+            // lazily scan the entries
+            this.entries = scan();
+        }
+        return this.entries;
+    }
+
+    /**
      * Returns the ClassFile matching the given binary name
      * or a fully-qualified class name.
      */
@@ -135,6 +162,20 @@
         }
     }
 
+    protected Set<String> scan() {
+        try {
+            ClassFile cf = ClassFile.read(path);
+            return Collections.singleton(cf.getName());
+        } catch (ConstantPoolException|IOException e) {
+            throw new ClassFileError(e);
+        }
+    }
+
+    static boolean isClass(Path file) {
+        String fn = file.getFileName().toString();
+        return fn.endsWith(".class") && !fn.equals(MODULE_INFO);
+    }
+
     class FileIterator implements Iterator<ClassFile> {
         int count;
         FileIterator() {
@@ -176,6 +217,19 @@
             this.fsSep = fs.getSeparator();
         }
 
+        protected Set<String> scan() {
+            try {
+                return Files.walk(path, Integer.MAX_VALUE)
+                        .filter(ClassFileReader::isClass)
+                        .map(f -> path.relativize(f))
+                        .map(Path::toString)
+                        .map(p -> p.replace(File.separatorChar, '/'))
+                        .collect(Collectors.toSet());
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
         public ClassFile getClassFile(String name) throws IOException {
             if (name.indexOf('.') > 0) {
                 int i = name.lastIndexOf('.');
@@ -206,28 +260,13 @@
             };
         }
 
-        private List<Path> entries;
-        protected synchronized List<Path> walkTree() throws IOException {
-            if (entries == null) {
-                entries = new ArrayList<>();
-                Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
-                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-                            throws IOException {
-                        if (file.getFileName().toString().endsWith(".class")) {
-                            entries.add(file);
-                        }
-                        return FileVisitResult.CONTINUE;
-                    }
-                });
-            }
-            return entries;
-        }
-
         class DirectoryIterator implements Iterator<ClassFile> {
             private List<Path> entries;
             private int index = 0;
             DirectoryIterator() throws IOException {
-                entries = walkTree();
+                entries = Files.walk(path, Integer.MAX_VALUE)
+                               .filter(ClassFileReader::isClass)
+                               .collect(Collectors.toList());
                 index = 0;
             }
 
@@ -264,6 +303,16 @@
             this.jarfile = jf;
         }
 
+        protected Set<String> scan() {
+            try (JarFile jf = new JarFile(path.toFile())) {
+                return jf.stream().map(JarEntry::getName)
+                         .filter(n -> n.endsWith(".class") && !n.endsWith(MODULE_INFO))
+                         .collect(Collectors.toSet());
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
         public ClassFile getClassFile(String name) throws IOException {
             if (name.indexOf('.') > 0) {
                 int i = name.lastIndexOf('.');
@@ -360,7 +409,7 @@
             while (entries.hasMoreElements()) {
                 JarEntry e = entries.nextElement();
                 String name = e.getName();
-                if (name.endsWith(".class")) {
+                if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
                     return e;
                 }
             }
@@ -371,29 +420,5 @@
             throw new UnsupportedOperationException("Not supported yet.");
         }
     }
-
-    /**
-     * ClassFileReader for modules.
-     */
-    static class ModuleClassReader extends DirectoryReader {
-        final String modulename;
-        ModuleClassReader(FileSystem fs, String mn, Path root) throws IOException {
-            super(fs, root);
-            this.modulename = mn;
-        }
-
-        public Set<String> packages() throws IOException {
-            return walkTree().stream()
-                             .map(this::toPackageName)
-                             .sorted()
-                             .collect(Collectors.toSet());
-        }
-
-        String toPackageName(Path p) {
-            if (p.getParent() == null) {
-                return "";
-            }
-            return path.relativize(p.getParent()).toString().replace(fsSep, ".");
-        }
-    }
+    private static final String MODULE_INFO = "module-info.class";
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java
new file mode 100644
index 0000000..086e13a
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+package com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Dependencies;
+import com.sun.tools.classfile.Dependency;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.sun.tools.jdeps.Module.*;
+import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE;
+
+public class DependencyFinder {
+    private final List<Archive> roots = new ArrayList<>();
+    private final List<Archive> classpaths = new ArrayList<>();
+    private final List<Module> modulepaths = new ArrayList<>();
+    private final List<String> classes = new ArrayList<>();
+    private final boolean compileTimeView;
+
+    DependencyFinder(boolean compileTimeView) {
+        this.compileTimeView = compileTimeView;
+    }
+
+    /*
+     * Adds a class name to the root set
+     */
+    void addClassName(String cn) {
+        classes.add(cn);
+    }
+
+    /*
+     * Adds the archive of the given path to the root set
+     */
+    void addRoot(Path path) {
+        addRoot(Archive.getInstance(path));
+    }
+
+    /*
+     * Adds the given archive to the root set
+     */
+    void addRoot(Archive archive) {
+        Objects.requireNonNull(archive);
+        if (!roots.contains(archive))
+            roots.add(archive);
+    }
+
+    /**
+     * Add an archive specified in the classpath.
+     */
+    void addClassPathArchive(Path path) {
+        addClassPathArchive(Archive.getInstance(path));
+    }
+
+    /**
+     * Add an archive specified in the classpath.
+     */
+    void addClassPathArchive(Archive archive) {
+        Objects.requireNonNull(archive);
+        classpaths.add(archive);
+    }
+
+    /**
+     * Add an archive specified in the modulepath.
+     */
+    void addModule(Module m) {
+        Objects.requireNonNull(m);
+        modulepaths.add(m);
+    }
+
+    /**
+     * Returns the root set.
+     */
+    List<Archive> roots() {
+        return roots;
+    }
+
+    /**
+     * Returns a stream of all archives including the root set, module paths,
+     * and classpath.
+     *
+     * This only returns the archives with classes parsed.
+     */
+    Stream<Archive> archives() {
+        Stream<Archive> archives = Stream.concat(roots.stream(), modulepaths.stream());
+        archives = Stream.concat(archives, classpaths.stream());
+        return archives.filter(a -> !a.isEmpty())
+                       .distinct();
+    }
+
+    /**
+     * Finds dependencies
+     *
+     * @param apiOnly  API only
+     * @param maxDepth depth of transitive dependency analysis; zero indicates
+     * @throws IOException
+     */
+    void findDependencies(JdepsFilter filter, boolean apiOnly, int maxDepth)
+            throws IOException
+    {
+        Dependency.Finder finder =
+                apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
+                        : Dependencies.getClassDependencyFinder();
+
+        // list of archives to be analyzed
+        Set<Archive> roots = new LinkedHashSet<>(this.roots);
+
+        // include java.base in root set
+        roots.add(JAVA_BASE);
+
+        // If -include pattern specified, classes may be in module path or class path.
+        // To get compile time view analysis, all classes are analyzed.
+        // add all modules except JDK modules to root set
+        modulepaths.stream()
+                   .filter(filter::matches)
+                   .forEach(roots::add);
+
+        // add classpath to the root set
+        classpaths.stream()
+                .filter(filter::matches)
+                .forEach(roots::add);
+
+        // transitive dependency
+        int depth = maxDepth > 0 ? maxDepth : Integer.MAX_VALUE;
+
+        // Work queue of names of classfiles to be searched.
+        // Entries will be unique, and for classes that do not yet have
+        // dependencies in the results map.
+        ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<>();
+        ConcurrentSkipListSet<String> doneClasses = new ConcurrentSkipListSet<>();
+
+        TaskExecutor executor = new TaskExecutor(finder, filter, apiOnly, deque, doneClasses);
+        try {
+            // get the immediate dependencies of the input files
+            for (Archive source : roots) {
+                executor.task(source, deque);
+            }
+            executor.waitForTasksCompleted();
+
+            List<Archive> archives = Stream.concat(Stream.concat(roots.stream(),
+                    modulepaths.stream()),
+                    classpaths.stream())
+                    .collect(Collectors.toList());
+
+            // Additional pass to find archive where dependences are identified
+            // and also any specified classes, if any.
+            // If -R is specified, perform transitive dependency analysis.
+            Deque<String> unresolved = new LinkedList<>(classes);
+            do {
+                String name;
+                while ((name = unresolved.poll()) != null) {
+                    if (doneClasses.contains(name)) {
+                        continue;
+                    }
+                    if (compileTimeView) {
+                        final String cn = name + ".class";
+                        // parse all classes in the source archive
+                        Optional<Archive> source = archives.stream()
+                                .filter(a -> a.reader().entries().contains(cn))
+                                .findFirst();
+                        trace("%s compile time view %s%n", name, source.map(Archive::getName).orElse(" not found"));
+                        if (source.isPresent()) {
+                            executor.runTask(source.get(), deque);
+                        }
+                    }
+                    ClassFile cf = null;
+                    for (Archive archive : archives) {
+                        cf = archive.reader().getClassFile(name);
+
+                        if (cf != null) {
+                            String classFileName;
+                            try {
+                                classFileName = cf.getName();
+                            } catch (ConstantPoolException e) {
+                                throw new Dependencies.ClassFileError(e);
+                            }
+                            if (!doneClasses.contains(classFileName)) {
+                                // if name is a fully-qualified class name specified
+                                // from command-line, this class might already be parsed
+                                doneClasses.add(classFileName);
+                                for (Dependency d : finder.findDependencies(cf)) {
+                                    if (depth == 0) {
+                                        // ignore the dependency
+                                        archive.addClass(d.getOrigin());
+                                        break;
+                                    } else if (filter.accepts(d) && filter.accept(archive)) {
+                                        // continue analysis on non-JDK classes
+                                        archive.addClass(d.getOrigin(), d.getTarget());
+                                        String cn = d.getTarget().getName();
+                                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
+                                            deque.add(cn);
+                                        }
+                                    } else {
+                                        // ensure that the parsed class is added the archive
+                                        archive.addClass(d.getOrigin());
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    if (cf == null) {
+                        doneClasses.add(name);
+                    }
+                }
+                unresolved = deque;
+                deque = new ConcurrentLinkedDeque<>();
+            } while (!unresolved.isEmpty() && depth-- > 0);
+        } finally {
+            executor.shutdown();
+        }
+     }
+
+    /**
+     * TaskExecutor creates FutureTask to analyze all classes in a given archive
+     */
+    private class TaskExecutor {
+        final ExecutorService pool;
+        final Dependency.Finder finder;
+        final JdepsFilter filter;
+        final boolean apiOnly;
+        final Set<String> doneClasses;
+        final Map<Archive, FutureTask<Void>> tasks = new HashMap<>();
+
+        TaskExecutor(Dependency.Finder finder,
+                     JdepsFilter filter,
+                     boolean apiOnly,
+                     ConcurrentLinkedDeque<String> deque,
+                     Set<String> doneClasses) {
+            this.pool = Executors.newFixedThreadPool(2);
+            this.finder = finder;
+            this.filter = filter;
+            this.apiOnly = apiOnly;
+            this.doneClasses = doneClasses;
+        }
+
+        /**
+         * Creates a new task to analyze class files in the given archive.
+         * The dependences are added to the given deque for analysis.
+         */
+        FutureTask<Void> task(Archive archive, final ConcurrentLinkedDeque<String> deque) {
+            trace("parsing %s %s%n", archive.getName(), archive.path());
+            FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
+                public Void call() throws Exception {
+                    for (ClassFile cf : archive.reader().getClassFiles()) {
+                        String classFileName;
+                        try {
+                            classFileName = cf.getName();
+                        } catch (ConstantPoolException e) {
+                            throw new Dependencies.ClassFileError(e);
+                        }
+
+                        // tests if this class matches the -include
+                        String cn = classFileName.replace('/', '.');
+                        if (!filter.matches(cn))
+                            continue;
+
+                        // if -apionly is specified, analyze only exported and public types
+                        if (apiOnly && !(isExported(archive, cn) && cf.access_flags.is(AccessFlags.ACC_PUBLIC)))
+                            continue;
+
+                        if (!doneClasses.contains(classFileName)) {
+                            doneClasses.add(classFileName);
+                        }
+
+                        for (Dependency d : finder.findDependencies(cf)) {
+                            if (filter.accepts(d) && filter.accept(archive)) {
+                                String name = d.getTarget().getName();
+                                if (!doneClasses.contains(name) && !deque.contains(name)) {
+                                    deque.add(name);
+                                }
+                                archive.addClass(d.getOrigin(), d.getTarget());
+                            } else {
+                                // ensure that the parsed class is added the archive
+                                archive.addClass(d.getOrigin());
+                            }
+                        }
+                    }
+                    return null;
+                }
+            });
+            tasks.put(archive, task);
+            pool.submit(task);
+            return task;
+        }
+
+        /*
+         * This task will parse all class files of the given archive, if it's a new task.
+         * This method waits until the task is completed.
+         */
+        void runTask(Archive archive, final ConcurrentLinkedDeque<String> deque) {
+            if (tasks.containsKey(archive))
+                return;
+
+            FutureTask<Void> task = task(archive, deque);
+            try {
+                // wait for completion
+                task.get();
+            } catch (InterruptedException|ExecutionException e) {
+                throw new Error(e);
+            }
+        }
+
+        /*
+         * Waits until all submitted tasks are completed.
+         */
+        void waitForTasksCompleted() {
+            try {
+                for (FutureTask<Void> t : tasks.values()) {
+                    if (t.isDone())
+                        continue;
+
+                    // wait for completion
+                    t.get();
+                }
+            } catch (InterruptedException|ExecutionException e) {
+                throw new Error(e);
+            }
+        }
+
+        /*
+         * Shutdown the executor service.
+         */
+        void shutdown() {
+            pool.shutdown();
+        }
+
+        /**
+         * Tests if the given class name is exported by the given archive.
+         *
+         * All packages are exported in unnamed module.
+         */
+        private boolean isExported(Archive archive, String classname) {
+            int i = classname.lastIndexOf('.');
+            String pn = i > 0 ? classname.substring(0, i) : "";
+            return archive.getModule().isExported(pn);
+        }
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java
new file mode 100644
index 0000000..84b04e2
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java
@@ -0,0 +1,249 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.Dependencies;
+import com.sun.tools.classfile.Dependency;
+import com.sun.tools.classfile.Dependency.Location;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/*
+ * Filter configured based on the input jdeps option
+ * 1. -p and -regex to match target dependencies
+ * 2. -filter:package to filter out same-package dependencies
+ *    This filter is applied when jdeps parses the class files
+ *    and filtered dependencies are not stored in the Analyzer.
+ * 3. -module specifies to match target dependencies from the given module
+ *    This gets expanded into package lists to be filtered.
+ * 4. -filter:archive to filter out same-archive dependencies
+ *    This filter is applied later in the Analyzer as the
+ *    containing archive of a target class may not be known until
+ *    the entire archive
+ */
+class JdepsFilter implements Dependency.Filter, Analyzer.Filter {
+    private final Dependency.Filter filter;
+    private final Pattern filterPattern;
+    private final boolean filterSamePackage;
+    private final boolean filterSameArchive;
+    private final boolean findJDKInternals;
+    private final Pattern includePattern;
+    private final Set<String> includePackages;
+    private final Set<String> excludeModules;
+
+    private JdepsFilter(Dependency.Filter filter,
+                        Pattern filterPattern,
+                        boolean filterSamePackage,
+                        boolean filterSameArchive,
+                        boolean findJDKInternals,
+                        Pattern includePattern,
+                        Set<String> includePackages,
+                        Set<String> excludeModules) {
+        this.filter = filter;
+        this.filterPattern = filterPattern;
+        this.filterSamePackage = filterSamePackage;
+        this.filterSameArchive = filterSameArchive;
+        this.findJDKInternals = findJDKInternals;
+        this.includePattern = includePattern;
+        this.includePackages = includePackages;
+        this.excludeModules = excludeModules;
+    }
+
+    /**
+     * Tests if the given class matches the pattern given in the -include option
+     *
+     * @param cn fully-qualified name
+     */
+    public boolean matches(String cn) {
+        if (includePackages.isEmpty() && includePattern == null)
+            return true;
+
+        int i = cn.lastIndexOf('.');
+        String pn = i > 0 ? cn.substring(0, i) : "";
+        if (includePackages.contains(pn))
+            return true;
+
+        if (includePattern != null)
+            return includePattern.matcher(cn).matches();
+
+        return false;
+    }
+
+    /**
+     * Tests if the given source includes classes specified in includePattern
+     * or includePackages filters.
+     *
+     * This method can be used to determine if the given source should eagerly
+     * be processed.
+     */
+    public boolean matches(Archive source) {
+        if (!includePackages.isEmpty() && source.getModule().isNamed()) {
+            boolean found = source.getModule().packages()
+                                  .stream()
+                                  .filter(pn -> includePackages.contains(pn))
+                                  .findAny().isPresent();
+            if (found)
+                return true;
+        }
+        if (!includePackages.isEmpty() || includePattern != null) {
+            return source.reader().entries()
+                         .stream()
+                         .map(name -> name.replace('/', '.'))
+                         .filter(this::matches)
+                         .findAny().isPresent();
+        }
+        return false;
+    }
+
+    // ----- Dependency.Filter -----
+
+    @Override
+    public boolean accepts(Dependency d) {
+        if (d.getOrigin().equals(d.getTarget()))
+            return false;
+
+        // filter same package dependency
+        String pn = d.getTarget().getPackageName();
+        if (filterSamePackage && d.getOrigin().getPackageName().equals(pn)) {
+            return false;
+        }
+
+        // filter if the target package matches the given filter
+        if (filterPattern != null && filterPattern.matcher(pn).matches()) {
+            return false;
+        }
+
+        // filter if the target matches the given filtered package name or regex
+        return filter != null ? filter.accepts(d) : true;
+    }
+
+    // ----- Analyzer.Filter ------
+
+    /**
+     * Filter depending on the containing archive or module
+     */
+    @Override
+    public boolean accepts(Location origin, Archive originArchive,
+                           Location target, Archive targetArchive) {
+        if (findJDKInternals) {
+            // accepts target that is JDK class but not exported
+            Module module = targetArchive.getModule();
+            return originArchive != targetArchive &&
+                    module.isJDK() && !module.isExported(target.getPackageName());
+        } else if (filterSameArchive) {
+            // accepts origin and target that from different archive
+            return originArchive != targetArchive;
+        }
+        return true;
+    }
+
+    /**
+     * Returns true if dependency should be recorded for the given source.
+     */
+    public boolean accept(Archive source) {
+        return !excludeModules.contains(source.getName());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("exclude modules: ")
+          .append(excludeModules.stream().sorted().collect(Collectors.joining(",")))
+          .append("\n");
+        sb.append("filter same archive: ").append(filterSameArchive).append("\n");
+        sb.append("filter same package: ").append(filterSamePackage).append("\n");
+        return sb.toString();
+    }
+
+    static class Builder {
+        Dependency.Filter filter;
+        Pattern filterPattern;
+        boolean filterSamePackage;
+        boolean filterSameArchive;
+        boolean findJDKInterals;
+        // source filters
+        Pattern includePattern;
+        Set<String> includePackages = new HashSet<>();
+        Set<String> includeModules = new HashSet<>();
+        Set<String> excludeModules = new HashSet<>();
+
+        public Builder packages(Set<String> packageNames) {
+            this.filter = Dependencies.getPackageFilter(packageNames, false);
+            return this;
+        }
+        public Builder regex(Pattern regex) {
+            this.filter = Dependencies.getRegexFilter(regex);
+            return this;
+        }
+        public Builder filter(Pattern regex) {
+            this.filterPattern = regex;
+            return this;
+        }
+        public Builder filter(boolean samePackage, boolean sameArchive) {
+            this.filterSamePackage = samePackage;
+            this.filterSameArchive = sameArchive;
+            return this;
+        }
+        public Builder findJDKInternals(boolean value) {
+            this.findJDKInterals = value;
+            return this;
+        }
+        public Builder includePattern(Pattern regex) {
+            this.includePattern = regex;
+            return this;
+        }
+        public Builder includePackage(String pn) {
+            this.includePackages.add(pn);
+            return this;
+        }
+        public Builder includeModules(Set<String> includes) {
+            this.includeModules.addAll(includes);
+            return this;
+        }
+        public Builder excludeModules(Set<String> excludes) {
+            this.excludeModules.addAll(excludes);
+            return this;
+        }
+
+        JdepsFilter build() {
+            return new JdepsFilter(filter,
+                                   filterPattern,
+                                   filterSamePackage,
+                                   filterSameArchive,
+                                   findJDKInterals,
+                                   includePattern,
+                                   includePackages,
+                                   excludeModules.stream()
+                                        .filter(mn -> !includeModules.contains(mn))
+                                        .collect(Collectors.toSet()));
+        }
+
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
index 2c62683..649e53e 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
@@ -25,22 +25,34 @@
 
 package com.sun.tools.jdeps;
 
-import com.sun.tools.classfile.AccessFlags;
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.classfile.ConstantPoolException;
-import com.sun.tools.classfile.Dependencies;
-import com.sun.tools.classfile.Dependencies.ClassFileError;
-import com.sun.tools.classfile.Dependency;
-import com.sun.tools.classfile.Dependency.Location;
 import static com.sun.tools.jdeps.Analyzer.Type.*;
-import java.io.*;
+import static com.sun.tools.jdeps.JdepsWriter.*;
+import static com.sun.tools.jdeps.ModuleAnalyzer.Graph;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.module.ResolutionException;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.text.MessageFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Implementation for the jdeps tool for static class dependency analysis.
@@ -145,11 +157,6 @@
                 }
             }
         },
-        new Option(true, "-cp", "-classpath") {
-            void process(JdepsTask task, String opt, String arg) {
-                task.options.classpath = arg;
-            }
-        },
         new Option(true, "-p", "-package") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.packageNames.add(arg);
@@ -157,17 +164,21 @@
         },
         new Option(true, "-e", "-regex") {
             void process(JdepsTask task, String opt, String arg) {
-                task.options.regex = arg;
+                task.options.regex = Pattern.compile(arg);
             }
         },
-
+        new Option(true, "-module") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.requires.add(arg);
+            }
+        },
         new Option(true, "-f", "-filter") {
             void process(JdepsTask task, String opt, String arg) {
-                task.options.filterRegex = arg;
+                task.options.filterRegex = Pattern.compile(arg);
             }
         },
         new Option(false, "-filter:package",
-                          "-filter:archive",
+                          "-filter:archive", "-filter:module",
                           "-filter:none") {
             void process(JdepsTask task, String opt, String arg) {
                 switch (opt) {
@@ -176,6 +187,7 @@
                         task.options.filterSameArchive = false;
                         break;
                     case "-filter:archive":
+                    case "-filter:module":
                         task.options.filterSameArchive = true;
                         task.options.filterSamePackage = false;
                         break;
@@ -197,7 +209,7 @@
                 task.options.showModule = false;
             }
         },
-        new Option(false, "-M", "-module") {
+        new Option(false, "-M") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 task.options.showModule = true;
                 task.options.showProfile = false;
@@ -216,6 +228,23 @@
                 task.options.filterSamePackage = false;
             }
         },
+        new Option(true, "-genmoduleinfo") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                Path p = Paths.get(arg);
+                if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
+                    throw new BadArgs("err.invalid.path", arg);
+                }
+                task.options.genModuleInfo = arg;
+            }
+        },
+        new Option(false, "-ct", "-compile-time") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.compileTimeView = true;
+                task.options.filterSamePackage = true;
+                task.options.filterSameArchive = true;
+                task.options.depth = 0;
+            }
+        },
         new Option(false, "-jdkinternals") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.findJDKInternals = true;
@@ -225,25 +254,55 @@
                 }
             }
         },
-            new HiddenOption(false, "-verify:access") {
-                void process(JdepsTask task, String opt, String arg) {
-                    task.options.verifyAccess = true;
-                    task.options.verbose = VERBOSE;
-                    task.options.filterSameArchive = false;
-                    task.options.filterSamePackage = false;
+        new Option(true, "-cp", "-classpath") {
+            void process(JdepsTask task, String opt, String arg) {
+                    task.options.classpath = arg;
                 }
-            },
-            new HiddenOption(true, "-mp") {
+        },
+        new Option(true, "-mp", "-modulepath") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.modulePath = arg;
+                task.options.showModule = true;
+            }
+        },
+        new Option(true, "-upgrademodulepath") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.upgradeModulePath = arg;
+                task.options.showModule = true;
+            }
+        },
+        new Option(true, "-m") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.rootModule = arg;
+                task.options.includes.add(arg);
+                task.options.showModule = true;
+            }
+        },
+        new Option(false, "-check") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.checkModuleDeps = true;
+            }
+        },
+        new HiddenOption(true, "-include-modules") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                Arrays.stream(arg.split(","))
+                        .forEach(task.options.includes::add);
+                task.options.showModule = true;
+            }
+        },
+        new HiddenOption(true, "-exclude-modules") {
                 void process(JdepsTask task, String opt, String arg) throws BadArgs {
-                    task.options.mpath = Paths.get(arg);
-                    if (!Files.isDirectory(task.options.mpath)) {
-                        throw new BadArgs("err.invalid.path", arg);
-                    }
-                    if (task.options.includePattern == null) {
-                        task.options.includePattern = Pattern.compile(".*");
-                    }
+                    Arrays.stream(arg.split(","))
+                            .forEach(task.options.excludes::add);
+                    task.options.showModule = true;
                 }
-            },
+        },
+        new Option(false, "-q", "-quiet") {
+            void process(JdepsTask task, String opt, String arg) {
+                    task.options.nowarning = true;
+                }
+        },
+
         new Option(false, "-version") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.version = true;
@@ -259,11 +318,7 @@
                 task.options.showLabel = true;
             }
         },
-        new HiddenOption(false, "-q", "-quiet") {
-            void process(JdepsTask task, String opt, String arg) {
-                task.options.nowarning = true;
-            }
-        },
+
         new HiddenOption(true, "-depth") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 try {
@@ -305,7 +360,15 @@
             if (options.version || options.fullVersion) {
                 showVersion(options.fullVersion);
             }
-            if (classes.isEmpty() && options.includePattern == null) {
+            if (options.rootModule != null && !classes.isEmpty()) {
+                reportError("err.invalid.module.option", options.rootModule, classes);
+                return EXIT_CMDERR;
+            }
+            if (options.checkModuleDeps && options.rootModule == null) {
+                reportError("err.root.module.not.set");
+                return EXIT_CMDERR;
+            }
+            if (classes.isEmpty() && options.rootModule == null && options.includePattern == null) {
                 if (options.help || options.version || options.fullVersion) {
                     return EXIT_OK;
                 } else {
@@ -313,12 +376,28 @@
                     return EXIT_CMDERR;
                 }
             }
-            if (options.regex != null && options.packageNames.size() > 0) {
-                showHelp();
+            if (options.genModuleInfo != null) {
+                if (options.dotOutputDir != null || !options.classpath.isEmpty() || options.hasFilter()) {
+                    showHelp();
+                    return EXIT_CMDERR;
+                }
+                // default to compile time view analysis
+                options.compileTimeView = true;
+                for (String fn : classes) {
+                    Path p = Paths.get(fn);
+                    if (!Files.exists(p) || !fn.endsWith(".jar")) {
+                        reportError("err.genmoduleinfo.not.jarfile", fn);
+                        return EXIT_CMDERR;
+                    }
+                }
+            }
+
+            if (options.numFilters() > 1) {
+                reportError("err.invalid.filters");
                 return EXIT_CMDERR;
             }
-            if ((options.findJDKInternals || options.verifyAccess) &&
-                   (options.regex != null || options.packageNames.size() > 0 || options.showSummary)) {
+
+            if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) {
                 showHelp();
                 return EXIT_CMDERR;
             }
@@ -335,140 +414,233 @@
                 log.println(getMessage("main.usage.summary", PROGNAME));
             }
             return EXIT_CMDERR;
+        } catch (ResolutionException e) {
+            reportError("err.exception.message", e.getMessage());
+            return EXIT_CMDERR;
         } catch (IOException e) {
+            e.printStackTrace();
             return EXIT_ABNORMAL;
         } finally {
             log.flush();
         }
     }
 
-    private final List<Archive> sourceLocations = new ArrayList<>();
-    private final List<Archive> classpaths = new ArrayList<>();
-    private final List<Archive> initialArchives = new ArrayList<>();
-    private boolean run() throws IOException {
-        buildArchives();
+    private ModulePaths modulePaths;
+    private boolean run() throws BadArgs, IOException {
+        DependencyFinder dependencyFinder =
+            new DependencyFinder(options.compileTimeView);
 
-        if (options.verifyAccess) {
-            return verifyModuleAccess();
+        buildArchive(dependencyFinder);
+
+        if (options.rootModule != null &&
+                (options.checkModuleDeps || (options.dotOutputDir != null &&
+                                      options.verbose == SUMMARY))) {
+            // -dotfile -s prints the configuration of the given root
+            // -checkModuleDeps prints the suggested module-info.java
+            return analyzeModules(dependencyFinder);
+        }
+
+        // otherwise analyze the dependencies
+        if (options.genModuleInfo != null) {
+            return genModuleInfo(dependencyFinder);
         } else {
-            return analyzeDeps();
+            return analyzeDeps(dependencyFinder);
         }
     }
 
-    private boolean analyzeDeps() throws IOException {
-        Analyzer analyzer = new Analyzer(options.verbose, new Analyzer.Filter() {
-            @Override
-            public boolean accepts(Location origin, Archive originArchive,
-                                   Location target, Archive targetArchive)
-            {
-                if (options.findJDKInternals) {
-                    // accepts target that is JDK class but not exported
-                    return isJDKModule(targetArchive) &&
-                              !((Module) targetArchive).isExported(target.getClassName());
-                } else if (options.filterSameArchive) {
-                    // accepts origin and target that from different archive
-                    return originArchive != targetArchive;
-                }
-                return true;
+    private void buildArchive(DependencyFinder dependencyFinder)
+            throws BadArgs, IOException
+    {
+        // If -genmoduleinfo is specified, the input arguments must be JAR files
+        // Treat them as automatic modules for analysis
+        List<Path> jarfiles = options.genModuleInfo != null
+                                    ?  classes.stream().map(Paths::get)
+                                              .collect(Collectors.toList())
+                                    : Collections.emptyList();
+        // Set module paths
+        this.modulePaths = new ModulePaths(options.upgradeModulePath, options.modulePath, jarfiles);
+
+        // add modules to dependency finder for analysis
+        Map<String, Module> modules = modulePaths.getModules();
+        modules.values().stream()
+               .forEach(dependencyFinder::addModule);
+
+        // If -m option is set, add the specified module and its transitive dependences
+        // to the root set
+        if (options.rootModule != null) {
+            modulePaths.dependences(options.rootModule)
+                       .forEach(dependencyFinder::addRoot);
+        }
+
+        // check if any module specified in -requires is missing
+        Optional<String> req = options.requires.stream()
+                .filter(mn -> !modules.containsKey(mn))
+                .findFirst();
+        if (req.isPresent()) {
+            throw new BadArgs("err.module.not.found", req.get());
+        }
+
+        // classpath
+        for (Path p : getClassPaths(options.classpath)) {
+            if (Files.exists(p)) {
+                dependencyFinder.addClassPathArchive(p);
             }
-        });
+        }
+
+        // if -genmoduleinfo is not set, the input arguments are considered as
+        // unnamed module.  Add them to the root set
+        if (options.genModuleInfo == null) {
+            // add root set
+            for (String s : classes) {
+                Path p = Paths.get(s);
+                if (Files.exists(p)) {
+                    // add to the initial root set
+                    dependencyFinder.addRoot(p);
+                } else {
+                    if (isValidClassName(s)) {
+                        dependencyFinder.addClassName(s);
+                    } else {
+                        warning("warn.invalid.arg", s);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean analyzeDeps(DependencyFinder dependencyFinder) throws IOException {
+        JdepsFilter filter = dependencyFilter();
 
         // parse classfiles and find all dependencies
-        findDependencies(options.apiOnly);
+        findDependencies(dependencyFinder, filter, options.apiOnly);
 
-        // analyze the dependencies
-        analyzer.run(sourceLocations);
+        // analyze the dependencies collected
+        Analyzer analyzer = new Analyzer(options.verbose, filter);
+        analyzer.run(dependencyFinder.archives());
 
         // output result
+        final JdepsWriter writer;
         if (options.dotOutputDir != null) {
             Path dir = Paths.get(options.dotOutputDir);
             Files.createDirectories(dir);
-            generateDotFiles(dir, analyzer);
+            writer = new DotFileWriter(dir, options.verbose,
+                                       options.showProfile,
+                                       options.showModule,
+                                       options.showLabel);
         } else {
-            printRawOutput(log, analyzer);
+            writer = new SimpleWriter(log, options.verbose,
+                                      options.showProfile,
+                                      options.showModule);
         }
 
+        // Targets for reporting - include the root sets and other analyzed archives
+        final List<Archive> targets;
+        if (options.rootModule == null) {
+            // no module as the root set
+            targets = dependencyFinder.archives()
+                                      .filter(filter::accept)
+                                      .filter(a -> !a.getModule().isNamed())
+                                      .collect(Collectors.toList());
+        } else {
+            // named modules in topological order
+            Stream<Module> modules = dependencyFinder.archives()
+                                                     .filter(a -> a.getModule().isNamed())
+                                                     .map(Archive::getModule);
+            Graph<Module> graph = ModuleAnalyzer.graph(modulePaths, modules.toArray(Module[]::new));
+            // then add unnamed module
+            targets = graph.orderedNodes()
+                           .filter(filter::accept)
+                           .collect(Collectors.toList());
+
+            // in case any reference not found
+            dependencyFinder.archives()
+                    .filter(a -> !a.getModule().isNamed())
+                    .forEach(targets::add);
+        }
+
+        writer.generateOutput(targets, analyzer);
         if (options.findJDKInternals && !options.nowarning) {
-            showReplacements(analyzer);
+            showReplacements(targets, analyzer);
         }
         return true;
     }
 
-    private boolean verifyModuleAccess() throws IOException {
-        // two passes
-        // 1. check API dependences where the types of dependences must be re-exported
-        // 2. check all dependences where types must be accessible
+    private JdepsFilter dependencyFilter() {
+        // Filter specified by -filter, -package, -regex, and -module options
+        JdepsFilter.Builder builder = new JdepsFilter.Builder();
 
-        // pass 1
-        findDependencies(true /* api only */);
-        Analyzer analyzer = Analyzer.getExportedAPIsAnalyzer();
-        boolean pass1 = analyzer.run(sourceLocations);
-        if (!pass1) {
-            System.out.println("ERROR: Failed API access verification");
+        // Exclude JDK modules from analysis and reporting if -m specified.
+        modulePaths.getModules().values().stream()
+                   .filter(m -> m.isJDK())
+                   .map(Module::name)
+                   .forEach(options.excludes::add);
+
+        // source filters
+        builder.includePattern(options.includePattern);
+        builder.includeModules(options.includes);
+        builder.excludeModules(options.excludes);
+
+        builder.filter(options.filterSamePackage, options.filterSameArchive);
+        builder.findJDKInternals(options.findJDKInternals);
+
+        // -module
+        if (!options.requires.isEmpty()) {
+            Map<String, Module> modules = modulePaths.getModules();
+            builder.packages(options.requires.stream()
+                    .map(modules::get)
+                    .flatMap(m -> m.packages().stream())
+                    .collect(Collectors.toSet()));
         }
-        // pass 2
-        findDependencies(false);
-        analyzer =  Analyzer.getModuleAccessAnalyzer();
-        boolean pass2 = analyzer.run(sourceLocations);
-        if (!pass2) {
-            System.out.println("ERROR: Failed module access verification");
-        }
-        if (pass1 & pass2) {
-            System.out.println("Access verification succeeded.");
-        }
-        return pass1 & pass2;
+        // -regex
+        if (options.regex != null)
+            builder.regex(options.regex);
+        // -package
+        if (!options.packageNames.isEmpty())
+            builder.packages(options.packageNames);
+        // -filter
+        if (options.filterRegex != null)
+            builder.filter(options.filterRegex);
+
+        return builder.build();
     }
 
-    private void generateSummaryDotFile(Path dir, Analyzer analyzer) throws IOException {
-        // If verbose mode (-v or -verbose option),
-        // the summary.dot file shows package-level dependencies.
-        Analyzer.Type summaryType =
-            (options.verbose == PACKAGE || options.verbose == SUMMARY) ? SUMMARY : PACKAGE;
-        Path summary = dir.resolve("summary.dot");
-        try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
-             SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) {
-            for (Archive archive : sourceLocations) {
-                if (!archive.isEmpty()) {
-                    if (options.verbose == PACKAGE || options.verbose == SUMMARY) {
-                        if (options.showLabel) {
-                            // build labels listing package-level dependencies
-                            analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE);
-                        }
-                    }
-                    analyzer.visitDependences(archive, dotfile, summaryType);
-                }
+    private void findDependencies(DependencyFinder dependencyFinder,
+                                  JdepsFilter filter,
+                                  boolean apiOnly)
+        throws IOException
+    {
+        dependencyFinder.findDependencies(filter, apiOnly, options.depth);
+
+        // print skipped entries, if any
+        for (Archive a : dependencyFinder.roots()) {
+            for (String name : a.reader().skippedEntries()) {
+                warning("warn.skipped.entry", name, a.getPathName());
             }
         }
     }
 
-    private void generateDotFiles(Path dir, Analyzer analyzer) throws IOException {
-        // output individual .dot file for each archive
-        if (options.verbose != SUMMARY) {
-            for (Archive archive : sourceLocations) {
-                if (analyzer.hasDependences(archive)) {
-                    Path dotfile = dir.resolve(archive.getName() + ".dot");
-                    try (PrintWriter pw = new PrintWriter(Files.newOutputStream(dotfile));
-                         DotFileFormatter formatter = new DotFileFormatter(pw, archive)) {
-                        analyzer.visitDependences(archive, formatter);
-                    }
-                }
-            }
-        }
-        // generate summary dot file
-        generateSummaryDotFile(dir, analyzer);
+    private boolean genModuleInfo(DependencyFinder dependencyFinder) throws IOException {
+        ModuleInfoBuilder builder = new ModuleInfoBuilder(modulePaths, dependencyFinder);
+        boolean result = builder.run(options.verbose, options.nowarning);
+        builder.build(Paths.get(options.genModuleInfo));
+        return result;
     }
 
-    private void printRawOutput(PrintWriter writer, Analyzer analyzer) {
-        RawOutputFormatter depFormatter = new RawOutputFormatter(writer);
-        RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer);
-        for (Archive archive : sourceLocations) {
-            if (!archive.isEmpty()) {
-                analyzer.visitDependences(archive, summaryFormatter, SUMMARY);
-                if (analyzer.hasDependences(archive) && options.verbose != SUMMARY) {
-                    analyzer.visitDependences(archive, depFormatter);
-                }
-            }
+    private boolean analyzeModules(DependencyFinder dependencyFinder)
+            throws IOException
+    {
+        ModuleAnalyzer analyzer = new ModuleAnalyzer(modulePaths,
+                                                     dependencyFinder,
+                                                     options.rootModule);
+        if (options.checkModuleDeps) {
+            return analyzer.run();
         }
+        if (options.dotOutputDir != null && options.verbose == SUMMARY) {
+            Path dir = Paths.get(options.dotOutputDir);
+            Files.createDirectories(dir);
+            analyzer.genDotFile(dir);
+            return true;
+        }
+        return false;
     }
 
     private boolean isValidClassName(String name) {
@@ -484,199 +656,6 @@
         return true;
     }
 
-    /*
-     * Dep Filter configured based on the input jdeps option
-     * 1. -p and -regex to match target dependencies
-     * 2. -filter:package to filter out same-package dependencies
-     *
-     * This filter is applied when jdeps parses the class files
-     * and filtered dependencies are not stored in the Analyzer.
-     *
-     * -filter:archive is applied later in the Analyzer as the
-     * containing archive of a target class may not be known until
-     * the entire archive
-     */
-    class DependencyFilter implements Dependency.Filter {
-        final Dependency.Filter filter;
-        final Pattern filterPattern;
-        DependencyFilter() {
-            if (options.regex != null) {
-                this.filter = Dependencies.getRegexFilter(Pattern.compile(options.regex));
-            } else if (options.packageNames.size() > 0) {
-                this.filter = Dependencies.getPackageFilter(options.packageNames, false);
-            } else {
-                this.filter = null;
-            }
-
-            this.filterPattern =
-                options.filterRegex != null ? Pattern.compile(options.filterRegex) : null;
-        }
-        @Override
-        public boolean accepts(Dependency d) {
-            if (d.getOrigin().equals(d.getTarget())) {
-                return false;
-            }
-            String pn = d.getTarget().getPackageName();
-            if (options.filterSamePackage && d.getOrigin().getPackageName().equals(pn)) {
-                return false;
-            }
-
-            if (filterPattern != null && filterPattern.matcher(pn).matches()) {
-                return false;
-            }
-            return filter != null ? filter.accepts(d) : true;
-        }
-    }
-
-    /**
-     * Tests if the given class matches the pattern given in the -include option
-     */
-    private boolean matches(String classname) {
-        if (options.includePattern != null) {
-            return options.includePattern.matcher(classname.replace('/', '.')).matches();
-        } else {
-            return true;
-        }
-    }
-
-    private void buildArchives() throws IOException {
-        for (String s : classes) {
-            Path p = Paths.get(s);
-            if (Files.exists(p)) {
-                initialArchives.add(Archive.getInstance(p));
-            }
-        }
-        sourceLocations.addAll(initialArchives);
-
-        classpaths.addAll(getClassPathArchives(options.classpath));
-        if (options.includePattern != null) {
-            initialArchives.addAll(classpaths);
-        }
-        classpaths.addAll(PlatformClassPath.getModules(options.mpath));
-        if (options.mpath != null) {
-            initialArchives.addAll(PlatformClassPath.getModules(options.mpath));
-        } else {
-            classpaths.addAll(PlatformClassPath.getJarFiles());
-        }
-        // add all classpath archives to the source locations for reporting
-        sourceLocations.addAll(classpaths);
-    }
-
-    private void findDependencies(boolean apiOnly) throws IOException {
-        Dependency.Finder finder =
-            apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
-                    : Dependencies.getClassDependencyFinder();
-        Dependency.Filter filter = new DependencyFilter();
-
-        Deque<String> roots = new LinkedList<>();
-        for (String s : classes) {
-            Path p = Paths.get(s);
-            if (!Files.exists(p)) {
-                if (isValidClassName(s)) {
-                    roots.add(s);
-                } else {
-                    warning("warn.invalid.arg", s);
-                }
-            }
-        }
-
-        // Work queue of names of classfiles to be searched.
-        // Entries will be unique, and for classes that do not yet have
-        // dependencies in the results map.
-        Deque<String> deque = new LinkedList<>();
-        Set<String> doneClasses = new HashSet<>();
-
-        // get the immediate dependencies of the input files
-        for (Archive a : initialArchives) {
-            for (ClassFile cf : a.reader().getClassFiles()) {
-                String classFileName;
-                try {
-                    classFileName = cf.getName();
-                } catch (ConstantPoolException e) {
-                    throw new ClassFileError(e);
-                }
-
-                // tests if this class matches the -include or -apiOnly option if specified
-                if (!matches(classFileName) || (apiOnly && !cf.access_flags.is(AccessFlags.ACC_PUBLIC))) {
-                    continue;
-                }
-
-                if (!doneClasses.contains(classFileName)) {
-                    doneClasses.add(classFileName);
-                }
-
-                for (Dependency d : finder.findDependencies(cf)) {
-                    if (filter.accepts(d)) {
-                        String cn = d.getTarget().getName();
-                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
-                            deque.add(cn);
-                        }
-                        a.addClass(d.getOrigin(), d.getTarget());
-                    } else {
-                        // ensure that the parsed class is added the archive
-                        a.addClass(d.getOrigin());
-                    }
-                }
-                for (String name : a.reader().skippedEntries()) {
-                    warning("warn.skipped.entry", name, a.getPathName());
-                }
-            }
-        }
-
-        // add Archive for looking up classes from the classpath
-        // for transitive dependency analysis
-        Deque<String> unresolved = roots;
-        int depth = options.depth > 0 ? options.depth : Integer.MAX_VALUE;
-        do {
-            String name;
-            while ((name = unresolved.poll()) != null) {
-                if (doneClasses.contains(name)) {
-                    continue;
-                }
-                ClassFile cf = null;
-                for (Archive a : classpaths) {
-                    cf = a.reader().getClassFile(name);
-                    if (cf != null) {
-                        String classFileName;
-                        try {
-                            classFileName = cf.getName();
-                        } catch (ConstantPoolException e) {
-                            throw new ClassFileError(e);
-                        }
-                        if (!doneClasses.contains(classFileName)) {
-                            // if name is a fully-qualified class name specified
-                            // from command-line, this class might already be parsed
-                            doneClasses.add(classFileName);
-
-                            for (Dependency d : finder.findDependencies(cf)) {
-                                if (depth == 0) {
-                                    // ignore the dependency
-                                    a.addClass(d.getOrigin());
-                                    break;
-                                } else if (filter.accepts(d)) {
-                                    a.addClass(d.getOrigin(), d.getTarget());
-                                    String cn = d.getTarget().getName();
-                                    if (!doneClasses.contains(cn) && !deque.contains(cn)) {
-                                        deque.add(cn);
-                                    }
-                                } else {
-                                    // ensure that the parsed class is added the archive
-                                    a.addClass(d.getOrigin());
-                                }
-                            }
-                        }
-                        break;
-                    }
-                }
-                if (cf == null) {
-                    doneClasses.add(name);
-                }
-            }
-            unresolved = deque;
-            deque = new LinkedList<>();
-        } while (!unresolved.isEmpty() && depth-- > 0);
-    }
-
     public void handleOptions(String[] args) throws BadArgs {
         // process options
         for (int i=0; i < args.length; i++) {
@@ -775,22 +754,45 @@
         boolean apiOnly;
         boolean showLabel;
         boolean findJDKInternals;
-        boolean nowarning;
+        boolean nowarning = false;
         // default is to show package-level dependencies
         // and filter references from same package
         Analyzer.Type verbose = PACKAGE;
         boolean filterSamePackage = true;
         boolean filterSameArchive = false;
-        String filterRegex;
+        Pattern filterRegex;
         String dotOutputDir;
+        String genModuleInfo;
         String classpath = "";
         int depth = 1;
+        Set<String> requires = new HashSet<>();
         Set<String> packageNames = new HashSet<>();
-        String regex;             // apply to the dependences
-        Pattern includePattern;   // apply to classes
-        // module boundary access check
-        boolean verifyAccess;
-        Path mpath;
+        Pattern regex;             // apply to the dependences
+        Pattern includePattern;    // apply to classes
+        boolean compileTimeView = false;
+        boolean checkModuleDeps = false;
+        String upgradeModulePath;
+        String modulePath;
+        String rootModule;
+        // modules to be included or excluded
+        Set<String> includes = new HashSet<>();
+        Set<String> excludes = new HashSet<>();
+
+        boolean hasFilter() {
+            return numFilters() > 0;
+        }
+
+        int numFilters() {
+            int count = 0;
+            if (requires.size() > 0) count++;
+            if (regex != null) count++;
+            if (packageNames.size() > 0) count++;
+            return count;
+        }
+
+        boolean isRootModule() {
+            return rootModule != null;
+        }
     }
     private static class ResourceBundleHelper {
         static final ResourceBundle versionRB;
@@ -821,12 +823,10 @@
      * Returns the list of Archive specified in cpaths and not included
      * initialArchives
      */
-    private List<Archive> getClassPathArchives(String cpaths)
-            throws IOException
+    private List<Path> getClassPaths(String cpaths) throws IOException
     {
-        List<Archive> result = new ArrayList<>();
         if (cpaths.isEmpty()) {
-            return result;
+            return Collections.emptyList();
         }
         List<Path> paths = new ArrayList<>();
         for (String p : cpaths.split(File.pathSeparator)) {
@@ -845,211 +845,7 @@
                 }
             }
         }
-        for (Path path : paths) {
-            boolean found = initialArchives.stream()
-                                           .map(Archive::path)
-                                           .anyMatch(p -> isSameFile(path, p));
-            if (!found && Files.exists(path)) {
-                result.add(Archive.getInstance(path));
-            }
-        }
-        return result;
-    }
-
-    private boolean isSameFile(Path p1, Path p2) {
-        try {
-            return Files.isSameFile(p1, p2);
-        } catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
-    class RawOutputFormatter implements Analyzer.Visitor {
-        private final PrintWriter writer;
-        private String pkg = "";
-        RawOutputFormatter(PrintWriter writer) {
-            this.writer = writer;
-        }
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String tag = toTag(target, targetArchive);
-            if (options.verbose == VERBOSE) {
-                writer.format("   %-50s -> %-50s %s%n", origin, target, tag);
-            } else {
-                if (!origin.equals(pkg)) {
-                    pkg = origin;
-                    writer.format("   %s (%s)%n", origin, originArchive.getName());
-                }
-                writer.format("      -> %-50s %s%n", target, tag);
-            }
-        }
-    }
-
-    class RawSummaryFormatter implements Analyzer.Visitor {
-        private final PrintWriter writer;
-        RawSummaryFormatter(PrintWriter writer) {
-            this.writer = writer;
-        }
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String targetName =  targetArchive.getPathName();
-            if (options.showModule && isJDKModule(targetArchive)) {
-                targetName = ((Module)targetArchive).name();
-            }
-            writer.format("%s -> %s", originArchive.getName(), targetName);
-            if (options.showProfile && isJDKModule(targetArchive)) {
-                writer.format(" (%s)", target);
-            }
-            writer.format("%n");
-        }
-    }
-
-    class DotFileFormatter implements Analyzer.Visitor, AutoCloseable {
-        private final PrintWriter writer;
-        private final String name;
-        DotFileFormatter(PrintWriter writer, Archive archive) {
-            this.writer = writer;
-            this.name = archive.getName();
-            writer.format("digraph \"%s\" {%n", name);
-            writer.format("    // Path: %s%n", archive.getPathName());
-        }
-
-        @Override
-        public void close() {
-            writer.println("}");
-        }
-
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String tag = toTag(target, targetArchive);
-            writer.format("   %-50s -> \"%s\";%n",
-                          String.format("\"%s\"", origin),
-                          tag.isEmpty() ? target
-                                        : String.format("%s (%s)", target, tag));
-        }
-    }
-
-    class SummaryDotFile implements Analyzer.Visitor, AutoCloseable {
-        private final PrintWriter writer;
-        private final Analyzer.Type type;
-        private final Map<Archive, Map<Archive,StringBuilder>> edges = new HashMap<>();
-        SummaryDotFile(PrintWriter writer, Analyzer.Type type) {
-            this.writer = writer;
-            this.type = type;
-            writer.format("digraph \"summary\" {%n");
-        }
-
-        @Override
-        public void close() {
-            writer.println("}");
-        }
-
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String targetName = type == PACKAGE ? target : targetArchive.getName();
-            if (isJDKModule(targetArchive)) {
-                Module m = (Module)targetArchive;
-                String n = showProfileOrModule(m);
-                if (!n.isEmpty()) {
-                    targetName += " (" + n + ")";
-                }
-            } else if (type == PACKAGE) {
-                targetName += " (" + targetArchive.getName() + ")";
-            }
-            String label = getLabel(originArchive, targetArchive);
-            writer.format("  %-50s -> \"%s\"%s;%n",
-                          String.format("\"%s\"", origin), targetName, label);
-        }
-
-        String getLabel(Archive origin, Archive target) {
-            if (edges.isEmpty())
-                return "";
-
-            StringBuilder label = edges.get(origin).get(target);
-            return label == null ? "" : String.format(" [label=\"%s\",fontsize=9]", label.toString());
-        }
-
-        Analyzer.Visitor labelBuilder() {
-            // show the package-level dependencies as labels in the dot graph
-            return new Analyzer.Visitor() {
-                @Override
-                public void visitDependence(String origin, Archive originArchive, String target, Archive targetArchive) {
-                    edges.putIfAbsent(originArchive, new HashMap<>());
-                    edges.get(originArchive).putIfAbsent(targetArchive, new StringBuilder());
-                    StringBuilder sb = edges.get(originArchive).get(targetArchive);
-                    String tag = toTag(target, targetArchive);
-                    addLabel(sb, origin, target, tag);
-                }
-
-                void addLabel(StringBuilder label, String origin, String target, String tag) {
-                    label.append(origin).append(" -> ").append(target);
-                    if (!tag.isEmpty()) {
-                        label.append(" (" + tag + ")");
-                    }
-                    label.append("\\n");
-                }
-            };
-        }
-    }
-
-    /**
-     * Test if the given archive is part of the JDK
-     */
-    private boolean isJDKModule(Archive archive) {
-        return Module.class.isInstance(archive);
-    }
-
-    /**
-     * If the given archive is JDK archive, this method returns the profile name
-     * only if -profile option is specified; it accesses a private JDK API and
-     * the returned value will have "JDK internal API" prefix
-     *
-     * For non-JDK archives, this method returns the file name of the archive.
-     */
-    private String toTag(String name, Archive source) {
-        if (!isJDKModule(source)) {
-            return source.getName();
-        }
-
-        Module module = (Module)source;
-        boolean isExported = false;
-        if (options.verbose == CLASS || options.verbose == VERBOSE) {
-            isExported = module.isExported(name);
-        } else {
-            isExported = module.isExportedPackage(name);
-        }
-        if (isExported) {
-            // exported API
-            return showProfileOrModule(module);
-        } else {
-            return "JDK internal API (" + source.getName() + ")";
-        }
-    }
-
-    private String showProfileOrModule(Module m) {
-        String tag = "";
-        if (options.showProfile) {
-            Profile p = Profile.getProfile(m);
-            if (p != null) {
-                tag = p.profileName();
-            }
-        } else if (options.showModule) {
-            tag = m.name();
-        }
-        return tag;
-    }
-
-    private Profile getProfile(String name) {
-        String pn = name;
-        if (options.verbose == CLASS || options.verbose == VERBOSE) {
-            int i = name.lastIndexOf('.');
-            pn = i > 0 ? name.substring(0, i) : "";
-        }
-        return Profile.getProfile(pn);
+        return paths;
     }
 
     /**
@@ -1071,10 +867,10 @@
         return value;
     };
 
-    private void showReplacements(Analyzer analyzer) {
+    private void showReplacements(List<Archive> archives, Analyzer analyzer) {
         Map<String,String> jdkinternals = new TreeMap<>();
         boolean useInternals = false;
-        for (Archive source : sourceLocations) {
+        for (Archive source : archives) {
             useInternals = useInternals || analyzer.hasDependences(source);
             for (String cn : analyzer.dependences(source)) {
                 String repl = replacementFor(cn);
@@ -1095,6 +891,6 @@
                 log.format("%-40s %s%n", e.getKey(), e.getValue());
             }
         }
-
     }
+
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java
new file mode 100644
index 0000000..06449fa
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java
@@ -0,0 +1,347 @@
+/*
+ * 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.
+ */
+package com.sun.tools.jdeps;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.sun.tools.jdeps.Analyzer.Type.*;
+
+public abstract class JdepsWriter {
+    final Analyzer.Type type;
+    final boolean showProfile;
+    final boolean showModule;
+
+    JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) {
+        this.type = type;
+        this.showProfile = showProfile;
+        this.showModule = showModule;
+    }
+
+    abstract void generateOutput(Collection<Archive> archives, Analyzer analyzer) throws IOException;
+
+    public static class DotFileWriter extends JdepsWriter {
+        final boolean showLabel;
+        final Path outputDir;
+        DotFileWriter(Path dir, Analyzer.Type type,
+                      boolean showProfile, boolean showModule, boolean showLabel) {
+            super(type, showProfile, showModule);
+            this.showLabel = showLabel;
+            this.outputDir = dir;
+        }
+
+        @Override
+        void generateOutput(Collection<Archive> archives, Analyzer analyzer)
+                throws IOException
+        {
+            // output individual .dot file for each archive
+            if (type != SUMMARY) {
+                archives.stream()
+                        .filter(analyzer::hasDependences)
+                        .forEach(archive -> {
+                            Path dotfile = outputDir.resolve(archive.getName() + ".dot");
+                            try (PrintWriter pw = new PrintWriter(Files.newOutputStream(dotfile));
+                                 DotFileFormatter formatter = new DotFileFormatter(pw, archive)) {
+                                analyzer.visitDependences(archive, formatter);
+                            } catch (IOException e) {
+                                throw new UncheckedIOException(e);
+                            }
+                        });
+            }
+            // generate summary dot file
+            generateSummaryDotFile(archives, analyzer);
+        }
+
+        private void generateSummaryDotFile(Collection<Archive> archives, Analyzer analyzer)
+                throws IOException
+        {
+            // If verbose mode (-v or -verbose option),
+            // the summary.dot file shows package-level dependencies.
+            Analyzer.Type summaryType =
+                (type == PACKAGE || type == SUMMARY) ? SUMMARY : PACKAGE;
+            Path summary = outputDir.resolve("summary.dot");
+            try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
+                 SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) {
+                for (Archive archive : archives) {
+                    if (type == PACKAGE || type == SUMMARY) {
+                        if (showLabel) {
+                            // build labels listing package-level dependencies
+                            analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE);
+                        }
+                    }
+                    analyzer.visitDependences(archive, dotfile, summaryType);
+                }
+            }
+        }
+
+        class DotFileFormatter implements Analyzer.Visitor, AutoCloseable {
+            private final PrintWriter writer;
+            private final String name;
+            DotFileFormatter(PrintWriter writer, Archive archive) {
+                this.writer = writer;
+                this.name = archive.getName();
+                writer.format("digraph \"%s\" {%n", name);
+                writer.format("    // Path: %s%n", archive.getPathName());
+            }
+
+            @Override
+            public void close() {
+                writer.println("}");
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+                String tag = toTag(originArchive, target, targetArchive);
+                writer.format("   %-50s -> \"%s\";%n",
+                              String.format("\"%s\"", origin),
+                              tag.isEmpty() ? target
+                                            : String.format("%s (%s)", target, tag));
+            }
+        }
+
+        class SummaryDotFile implements Analyzer.Visitor, AutoCloseable {
+            private final PrintWriter writer;
+            private final Analyzer.Type type;
+            private final Map<Archive, Map<Archive,StringBuilder>> edges = new HashMap<>();
+            SummaryDotFile(PrintWriter writer, Analyzer.Type type) {
+                this.writer = writer;
+                this.type = type;
+                writer.format("digraph \"summary\" {%n");
+            }
+
+            @Override
+            public void close() {
+                writer.println("}");
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+
+                String targetName = type == PACKAGE ? target : targetArchive.getName();
+                if (targetArchive.getModule().isJDK()) {
+                    Module m = (Module)targetArchive;
+                    String n = showProfileOrModule(m);
+                    if (!n.isEmpty()) {
+                        targetName += " (" + n + ")";
+                    }
+                } else if (type == PACKAGE) {
+                    targetName += " (" + targetArchive.getName() + ")";
+                }
+                String label = getLabel(originArchive, targetArchive);
+                writer.format("  %-50s -> \"%s\"%s;%n",
+                        String.format("\"%s\"", origin), targetName, label);
+            }
+
+            String getLabel(Archive origin, Archive target) {
+                if (edges.isEmpty())
+                    return "";
+
+                StringBuilder label = edges.get(origin).get(target);
+                return label == null ? "" : String.format(" [label=\"%s\",fontsize=9]", label.toString());
+            }
+
+            Analyzer.Visitor labelBuilder() {
+                // show the package-level dependencies as labels in the dot graph
+                return new Analyzer.Visitor() {
+                    @Override
+                    public void visitDependence(String origin, Archive originArchive,
+                                                String target, Archive targetArchive)
+                    {
+                        edges.putIfAbsent(originArchive, new HashMap<>());
+                        edges.get(originArchive).putIfAbsent(targetArchive, new StringBuilder());
+                        StringBuilder sb = edges.get(originArchive).get(targetArchive);
+                        String tag = toTag(originArchive, target, targetArchive);
+                        addLabel(sb, origin, target, tag);
+                    }
+
+                    void addLabel(StringBuilder label, String origin, String target, String tag) {
+                        label.append(origin).append(" -> ").append(target);
+                        if (!tag.isEmpty()) {
+                            label.append(" (" + tag + ")");
+                        }
+                        label.append("\\n");
+                    }
+                };
+            }
+        }
+    }
+
+    static class SimpleWriter extends JdepsWriter {
+        final PrintWriter writer;
+        SimpleWriter(PrintWriter writer, Analyzer.Type type,
+                     boolean showProfile, boolean showModule) {
+            super(type, showProfile, showModule);
+            this.writer = writer;
+        }
+
+        @Override
+        void generateOutput(Collection<Archive> archives, Analyzer analyzer) {
+            RawOutputFormatter depFormatter = new RawOutputFormatter(writer);
+            RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer);
+            for (Archive archive : archives) {
+                // print summary
+                if (showModule && archive.getModule().isNamed()) {
+                    summaryFormatter.showModuleRequires(archive.getModule());
+                } else {
+                    analyzer.visitDependences(archive, summaryFormatter, SUMMARY);
+                }
+
+                if (analyzer.hasDependences(archive) && type != SUMMARY) {
+                    // print the class-level or package-level dependences
+                    analyzer.visitDependences(archive, depFormatter);
+                }
+            }
+        }
+
+        class RawOutputFormatter implements Analyzer.Visitor {
+            private final PrintWriter writer;
+            private String pkg = "";
+
+            RawOutputFormatter(PrintWriter writer) {
+                this.writer = writer;
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+                String tag = toTag(originArchive, target, targetArchive);
+                if (showModule || type == VERBOSE) {
+                    writer.format("   %-50s -> %-50s %s%n", origin, target, tag);
+                } else {
+                    if (!origin.equals(pkg)) {
+                        pkg = origin;
+                        writer.format("   %s (%s)%n", origin, originArchive.getName());
+                    }
+                    writer.format("      -> %-50s %s%n", target, tag);
+                }
+            }
+        }
+
+        class RawSummaryFormatter implements Analyzer.Visitor {
+            private final PrintWriter writer;
+
+            RawSummaryFormatter(PrintWriter writer) {
+                this.writer = writer;
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+
+                String targetName = targetArchive.getPathName();
+                if (targetArchive.getModule().isNamed()) {
+                    targetName = targetArchive.getModule().name();
+                }
+                writer.format("%s -> %s", originArchive.getName(), targetName);
+                if (showProfile && targetArchive.getModule().isJDK()) {
+                    writer.format(" (%s)", target);
+                }
+                writer.format("%n");
+            }
+
+            public void showModuleRequires(Module module) {
+                if (!module.isNamed())
+                    return;
+
+                writer.format("module %s", module.name());
+                if (module.isAutomatic())
+                    writer.format(" (automatic)");
+                writer.println();
+                module.requires().keySet()
+                        .stream()
+                        .sorted()
+                        .forEach(req -> writer.format(" requires %s%s%n",
+                                                      module.requires.get(req) ? "public " : "",
+                                                      req));
+            }
+        }
+    }
+
+    /**
+     * If the given archive is JDK archive, this method returns the profile name
+     * only if -profile option is specified; it accesses a private JDK API and
+     * the returned value will have "JDK internal API" prefix
+     *
+     * For non-JDK archives, this method returns the file name of the archive.
+     */
+    String toTag(Archive source, String name, Archive target) {
+        if (source == target || !target.getModule().isNamed()) {
+            return target.getName();
+        }
+
+        Module module = target.getModule();
+        String pn = name;
+        if ((type == CLASS || type == VERBOSE)) {
+            int i = name.lastIndexOf('.');
+            pn = i > 0 ? name.substring(0, i) : "";
+        }
+
+        // exported API
+        boolean jdkunsupported = Module.isJDKUnsupported(module, pn);
+        if (module.isExported(pn) && !jdkunsupported) {
+            return showProfileOrModule(module);
+        }
+
+        // JDK internal API
+        if (!source.getModule().isJDK() && module.isJDK()){
+            return "JDK internal API (" + module.name() + ")";
+        }
+
+        // qualified exports or inaccessible
+        boolean isExported = module.isExported(pn, source.getModule().name());
+        return module.name() + (isExported ?  " (qualified)" : " (internal)");
+    }
+
+    String showProfileOrModule(Module m) {
+        String tag = "";
+        if (showProfile) {
+            Profile p = Profile.getProfile(m);
+            if (p != null) {
+                tag = p.profileName();
+            }
+        } else if (showModule) {
+            tag = m.name();
+        }
+        return tag;
+    }
+
+    Profile getProfile(String name) {
+        String pn = name;
+        if (type == CLASS || type == VERBOSE) {
+            int i = name.lastIndexOf('.');
+            pn = i > 0 ? name.substring(0, i) : "";
+        }
+        return Profile.getProfile(pn);
+    }
+
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
index 9da197e4..a3ede30 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
@@ -25,35 +25,94 @@
 
 package com.sun.tools.jdeps;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.net.URI;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
 
 /**
  * JDeps internal representation of module for dependency analysis.
  */
-final class Module extends Archive {
-    private final String moduleName;
-    private final Map<String, Boolean> requires;
-    private final Map<String, Set<String>> exports;
-    private final Set<String> packages;
+class Module extends Archive {
+    static final boolean traceOn = Boolean.getBoolean("jdeps.debug");
+    static void trace(String fmt, Object... args) {
+        if (traceOn) {
+            System.err.format(fmt, args);
+        }
+    }
 
-    private Module(ClassFileReader reader, String name,
+    /*
+     * Returns true if the given package name is JDK critical internal API
+     * in jdk.unsupported module
+     */
+    static boolean isJDKUnsupported(Module m, String pn) {
+        return JDK_UNSUPPORTED.equals(m.name()) || unsupported.contains(pn);
+    };
+
+    protected final ModuleDescriptor descriptor;
+    protected final Map<String, Boolean> requires;
+    protected final Map<String, Set<String>> exports;
+    protected final Set<String> packages;
+    protected final boolean isJDK;
+    protected final URI location;
+
+    private Module(String name,
+                   URI location,
+                   ModuleDescriptor descriptor,
                    Map<String, Boolean> requires,
                    Map<String, Set<String>> exports,
-                   Set<String> packages) {
-        super(name, reader);
-        this.moduleName = name;
+                   Set<String> packages,
+                   boolean isJDK,
+                   ClassFileReader reader) {
+        super(name, location, reader);
+        this.descriptor = descriptor;
+        this.location = location;
         this.requires = Collections.unmodifiableMap(requires);
         this.exports = Collections.unmodifiableMap(exports);
         this.packages = Collections.unmodifiableSet(packages);
+        this.isJDK = isJDK;
     }
 
+    /**
+     * Returns module name
+     */
     public String name() {
-        return moduleName;
+        return descriptor.name();
+    }
+
+    public boolean isNamed() {
+        return true;
+    }
+
+    public boolean isAutomatic() {
+        return descriptor.isAutomatic();
+    }
+
+    public Module getModule() {
+        return this;
+    }
+
+    public ModuleDescriptor descriptor() {
+        return descriptor;
+    }
+
+    public boolean isJDK() {
+        return isJDK;
     }
 
     public Map<String, Boolean> requires() {
@@ -64,89 +123,46 @@
         return exports;
     }
 
+    public Map<String, Set<String>> provides() {
+        return descriptor.provides().entrySet().stream()
+                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().providers()));
+    }
+
     public Set<String> packages() {
         return packages;
     }
 
     /**
-     * Tests if this module can read m
+     * Tests if the package of the given name is exported.
      */
-    public boolean canRead(Module m) {
-        // ## TODO: handle "re-exported=true"
-        // all JDK modules require all modules containing its direct dependences
-        // should not be an issue
-        return requires.containsKey(m.name());
-    }
-
-    /**
-     * Tests if a given fully-qualified name is an exported type.
-     */
-    public boolean isExported(String cn) {
-        int i = cn.lastIndexOf('.');
-        String pn = i > 0 ? cn.substring(0, i) : "";
-
-        return isExportedPackage(pn);
-    }
-
-    /**
-     * Tests if a given package name is exported.
-     */
-    public boolean isExportedPackage(String pn) {
+    public boolean isExported(String pn) {
         return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false;
     }
 
     /**
-     * Tests if the given classname is accessible to module m
+     * Converts this module to a strict module with the given dependences
+     *
+     * @throws IllegalArgumentException if this module is not an automatic module
      */
-    public boolean isAccessibleTo(String classname, Module m) {
-        int i = classname.lastIndexOf('.');
-        String pn = i > 0 ? classname.substring(0, i) : "";
-        if (!packages.contains(pn)) {
-            throw new IllegalArgumentException(classname + " is not a member of module " + name());
+    public Module toStrictModule(Map<String, Boolean> requires) {
+        if (!isAutomatic()) {
+            throw new IllegalArgumentException(name() + " already a strict module");
         }
-
-        if (m != null && !m.canRead(this)) {
-            trace("%s not readable by %s%n", this.name(), m.name());
-            return false;
-        }
-
-        // exported API
-        Set<String> ms = exports().get(pn);
-        String mname = m != null ? m.name() : "unnamed";
-        if (ms == null) {
-            trace("%s not exported in %s%n", classname, this.name());
-        } else if (!(ms.isEmpty() || ms.contains(mname))) {
-            trace("%s not permit to %s %s%n", classname, mname, ms);
-        }
-        return ms != null && (ms.isEmpty() || ms.contains(mname));
+        return new StrictModule(this, requires);
     }
 
-    private static final boolean traceOn = Boolean.getBoolean("jdeps.debug");
-    private void trace(String fmt, Object... args) {
-        if (traceOn) {
-            System.err.format(fmt, args);
-        }
+    /**
+     * Tests if the package of the given name is qualifiedly exported
+     * to the target.
+     */
+    public boolean isExported(String pn, String target) {
+        return isExported(pn) || exports.containsKey(pn) && exports.get(pn).contains(target);
     }
 
-    @Override
-    public boolean equals(Object ob) {
-        if (!(ob instanceof Module))
-            return false;
-        Module that = (Module)ob;
-        return (moduleName.equals(that.moduleName)
-                && requires.equals(that.requires)
-                && exports.equals(that.exports)
-                && packages.equals(that.packages));
-    }
+    private final static String JDK_UNSUPPORTED = "jdk.unsupported";
 
-    @Override
-    public int hashCode() {
-        int hc = moduleName.hashCode();
-        hc = hc * 43 + requires.hashCode();
-        hc = hc * 43 + exports.hashCode();
-        hc = hc * 43 + packages.hashCode();
-        return hc;
-    }
+    // temporary until jdk.unsupported module
+    private final static List<String> unsupported = Arrays.asList("sun.misc", "sun.reflect");
 
     @Override
     public String toString() {
@@ -154,22 +170,35 @@
     }
 
     public final static class Builder {
-        String name;
-        ClassFileReader reader;
+        final String name;
         final Map<String, Boolean> requires = new HashMap<>();
         final Map<String, Set<String>> exports = new HashMap<>();
         final Set<String> packages = new HashSet<>();
+        final boolean isJDK;
+        ClassFileReader reader;
+        ModuleDescriptor descriptor;
+        URI location;
 
-        public Builder() {
+        public Builder(String name) {
+            this(name, false);
         }
 
-        public Builder name(String n) {
-            name = n;
+        public Builder(String name, boolean isJDK) {
+            this.name = name;
+            this.isJDK = isJDK;
+        }
+
+        public Builder location(URI location) {
+            this.location = location;
+            return this;
+        }
+
+        public Builder descriptor(ModuleDescriptor md) {
+            this.descriptor = md;
             return this;
         }
 
         public Builder require(String d, boolean reexport) {
-         //   System.err.format("%s depend %s reexports %s%n", name, d, reexport);
             requires.put(d, reexport);
             return this;
         }
@@ -185,14 +214,172 @@
             exports.put(p, new HashSet<>(ms));
             return this;
         }
-        public Builder classes(ClassFileReader.ModuleClassReader reader) {
+        public Builder classes(ClassFileReader reader) {
             this.reader = reader;
             return this;
         }
 
         public Module build() {
-            Module m = new Module(reader, name, requires, exports, packages);
-            return m;
+            if (descriptor.isAutomatic() && isJDK) {
+                throw new InternalError("JDK module: " + name + " can't be automatic module");
+            }
+
+            return new Module(name, location, descriptor, requires, exports, packages, isJDK, reader);
+        }
+    }
+
+    final static Module UNNAMED_MODULE = new UnnamedModule();
+    private static class UnnamedModule extends Module {
+        private UnnamedModule() {
+            super("unnamed", null, null,
+                  Collections.emptyMap(),
+                  Collections.emptyMap(),
+                  Collections.emptySet(),
+                  false, null);
+        }
+
+        @Override
+        public String name() {
+            return "unnamed";
+        }
+
+        @Override
+        public boolean isNamed() {
+            return false;
+        }
+
+        @Override
+        public boolean isAutomatic() {
+            return false;
+        }
+
+        @Override
+        public boolean isExported(String pn) {
+            return true;
+        }
+    }
+
+    private static class StrictModule extends Module {
+        private static final String SERVICES_PREFIX = "META-INF/services/";
+        private final Map<String, Set<String>> provides;
+        private final Module module;
+        private final JarFile jarfile;
+
+        /**
+         * Converts the given automatic module to a strict module.
+         *
+         * Replace this module's dependences with the given requires and also
+         * declare service providers, if specified in META-INF/services configuration file
+         */
+        private StrictModule(Module m, Map<String, Boolean> requires) {
+            super(m.name(), m.location, m.descriptor, requires, m.exports, m.packages, m.isJDK, m.reader());
+            this.module = m;
+            try {
+                this.jarfile = new JarFile(m.path().toFile(), false);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+            this.provides = providers(jarfile);
+        }
+
+        @Override
+        public Map<String, Set<String>> provides() {
+            return provides;
+        }
+
+        private Map<String, Set<String>> providers(JarFile jf) {
+            Map<String, Set<String>> provides = new HashMap<>();
+            // map names of service configuration files to service names
+            Set<String> serviceNames =  jf.stream()
+                    .map(e -> e.getName())
+                    .filter(e -> e.startsWith(SERVICES_PREFIX))
+                    .distinct()
+                    .map(this::toServiceName)
+                    .filter(Optional::isPresent)
+                    .map(Optional::get)
+                    .collect(Collectors.toSet());
+
+            // parse each service configuration file
+            for (String sn : serviceNames) {
+                JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
+                Set<String> providerClasses = new HashSet<>();
+                try (InputStream in = jf.getInputStream(entry)) {
+                    BufferedReader reader
+                            = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+                    String cn;
+                    while ((cn = nextLine(reader)) != null) {
+                        if (isJavaIdentifier(cn)) {
+                            providerClasses.add(cn);
+                        }
+                    }
+                } catch (IOException e) {
+                    throw new UncheckedIOException(e);
+                }
+                if (!providerClasses.isEmpty())
+                    provides.put(sn, providerClasses);
+            }
+
+            return provides;
+        }
+
+        /**
+         * Returns a container with the service type corresponding to the name of
+         * a services configuration file.
+         *
+         * For example, if called with "META-INF/services/p.S" then this method
+         * returns a container with the value "p.S".
+         */
+        private Optional<String> toServiceName(String cf) {
+            assert cf.startsWith(SERVICES_PREFIX);
+            int index = cf.lastIndexOf("/") + 1;
+            if (index < cf.length()) {
+                String prefix = cf.substring(0, index);
+                if (prefix.equals(SERVICES_PREFIX)) {
+                    String sn = cf.substring(index);
+                    if (isJavaIdentifier(sn))
+                        return Optional.of(sn);
+                }
+            }
+            return Optional.empty();
+        }
+
+        /**
+         * Reads the next line from the given reader and trims it of comments and
+         * leading/trailing white space.
+         *
+         * Returns null if the reader is at EOF.
+         */
+        private String nextLine(BufferedReader reader) throws IOException {
+            String ln = reader.readLine();
+            if (ln != null) {
+                int ci = ln.indexOf('#');
+                if (ci >= 0)
+                    ln = ln.substring(0, ci);
+                ln = ln.trim();
+            }
+            return ln;
+        }
+
+        /**
+         * Returns {@code true} if the given identifier is a legal Java identifier.
+         */
+        private static boolean isJavaIdentifier(String id) {
+            int n = id.length();
+            if (n == 0)
+                return false;
+            if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
+                return false;
+            int cp = id.codePointAt(0);
+            int i = Character.charCount(cp);
+            for (; i < n; i += Character.charCount(cp)) {
+                cp = id.codePointAt(i);
+                if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
+                    return false;
+            }
+            if (cp == '.')
+                return false;
+
+            return true;
         }
     }
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java
new file mode 100644
index 0000000..f419e56
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java
@@ -0,0 +1,708 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.sun.tools.jdeps.Module.*;
+import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE;
+
+/**
+ * Analyze module dependences and compare with module descriptor.
+ * Also identify any qualified exports not used by the target module.
+ */
+class ModuleAnalyzer {
+    private final ModulePaths modulePaths;
+    private final DependencyFinder dependencyFinder;
+    private final Module root;
+    private final Set<Module> modules;
+    private final Set<String> requiresPublic = new HashSet<>();
+    private final Set<String> requires = new HashSet<>();
+    private final Set<Module> exportTargets = new HashSet<>();
+    private final JdepsFilter filter;
+    private Graph<Module> graph;
+    ModuleAnalyzer(ModulePaths modulePaths, DependencyFinder finder,
+                   String moduleName) {
+        this.modulePaths = modulePaths;
+        this.dependencyFinder = finder;
+        this.root = modulePaths.getModules().get(moduleName);
+        this.modules = modulePaths.dependences(moduleName);
+
+        root.exports().values().stream()
+             .flatMap(Set::stream)
+             .map(target -> modulePaths.getModules().get(target))
+             .forEach(this.exportTargets::add);
+
+        this.filter = new JdepsFilter.Builder().filter(true, true).build();
+    }
+
+    /**
+     * Returns a graph of transitive closure of the given modules.
+     *
+     * This method does not add the implicit read edges and is intended to
+     * get all transitive closures in (reverse) topological sort.
+     */
+    public static Graph<Module> graph(ModulePaths modulePaths, Module... modules) {
+        Graph.Builder<Module> gb = new Graph.Builder<>();
+        for (Module module : modules) {
+            module.descriptor().requires().stream()
+                    .map(ModuleDescriptor.Requires::name)
+                    .map(mn -> modulePaths.getModules().get(mn))
+                    .forEach(m -> {
+                        gb.addNode(m);
+                        gb.addEdge(module, m);
+                    });
+        }
+        return gb.build();
+    }
+
+    /**
+     * Do the analysis
+     */
+    public boolean run() {
+        try {
+            computeRequiresPublic();
+            computeRequires();
+            // apply transitive reduction and reports recommended requires.
+            analyzeDeps();
+            // detect any qualiifed exports not used by the target module
+            checkQualifiedExports();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return true;
+    }
+
+    /**
+     * Compute 'requires public' dependences by analyzing API dependencies
+     */
+    private void computeRequiresPublic() throws IOException {
+        JdepsFilter.Builder builder = new JdepsFilter.Builder();
+        // only analyze exported API
+        root.descriptor.exports().stream()
+                .filter(exp -> !exp.isQualified())
+                .map(ModuleDescriptor.Exports::source)
+                .forEach(builder::includePackage);
+
+        JdepsFilter filter = builder.filter(true, true).build();
+
+        // analyze dependences for exported packages
+        dependencyFinder.findDependencies(filter, true /* api only */, 1);
+        Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
+        analyzer.run(modules);
+
+        // record requires public
+        analyzer.requires(root)
+                .filter(m -> m != JAVA_BASE && m != root)
+                .map(Archive::getName)
+                .forEach(requiresPublic::add);
+        trace("requires public: %s%n", requiresPublic);
+    }
+
+    private void computeRequires() throws IOException {
+        // add the exportTargets of the qualified exports to the root set
+        exportTargets.stream()
+                .peek(target -> trace("add root: %s%n", target))
+                .forEach(dependencyFinder::addRoot);
+
+        // analyze all classes
+        dependencyFinder.findDependencies(filter, false /* all classes */, 1);
+        Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
+        analyzer.run(modules);
+
+        // record requires
+        analyzer.requires(root)
+                .filter(m -> m != JAVA_BASE && m != root)
+                .map(Archive::getName)
+                .forEach(requires::add);
+
+        this.graph = buildGraph(analyzer, root);
+        if (traceOn) {
+            trace("dependences: %s%n", graph.nodes());
+            graph.printGraph(System.out);
+        }
+    }
+
+    /**
+     * Apply transitive reduction on the resulting graph and reports
+     * recommended requires.
+     */
+    private void analyzeDeps() {
+        String moduleName = root.name();
+
+        Graph.Builder<String> builder = new Graph.Builder<>();
+        requiresPublic.stream()
+                .forEach(mn -> {
+                    builder.addNode(mn);
+                    builder.addEdge(moduleName, mn);
+                });
+        // requires public graph
+        Graph<String> rbg = builder.build().reduce();
+
+        // convert the dependence graph from Module to name
+        Set<String> nodes = this.graph.nodes().stream()
+                .map(Module::name)
+                .collect(Collectors.toSet());
+        Map<String, Set<String>> edges = new HashMap<>();
+        this.graph.edges().keySet().stream()
+                .forEach(m -> {
+                    String mn = m.name();
+                    Set<String> es = edges.computeIfAbsent(mn, _k -> new HashSet<String>());
+                    this.graph.edges().get(m).stream()
+                            .map(Module::name)
+                            .forEach(es::add);
+                });
+
+        // transitive reduction
+        Graph<String> newGraph = new Graph<>(nodes, edges).reduce(rbg);
+        if (traceOn) {
+            System.out.println("after transitive reduction");
+            newGraph.printGraph(System.out);
+        };
+
+        Set<String> reducedRequires = newGraph.adjacentNodes(moduleName);
+        if (matches(root.descriptor(), requires, requiresPublic) &&
+                matches(root.descriptor(), reducedRequires, requiresPublic)) {
+            System.out.println("--- Analysis result: no change for " + root.name());
+        } else {
+            System.out.println("--- Analysis result: suggested requires for " + root.name());
+            System.out.format("module %s%n", root.name());
+                requires.stream()
+                        .sorted()
+                        .forEach(dn -> System.out.format("  requires %s%s;%n",
+                                requiresPublic.contains(dn) ? "public " : "", dn));
+            if (!requires.equals(reducedRequires) && !reducedRequires.isEmpty()) {
+                System.out.format("%nmodule %s (reduced)%n", root.name());
+                newGraph.adjacentNodes(moduleName)
+                     .stream()
+                     .sorted()
+                     .forEach(dn -> System.out.format("  requires %s%s;%n",
+                                requiresPublic.contains(dn) ? "public " : "", dn));
+            }
+            System.out.println("\n---  Module descriptor");
+            Graph<Module> mdGraph = graph(modulePaths, root);
+            mdGraph.reverse(m -> printModuleDescriptor(System.out, m.descriptor()));
+        }
+    }
+
+    /**
+     * Detects any qualified exports not used by the target module.
+     */
+    private void checkQualifiedExports() throws IOException {
+        Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
+        analyzer.run(dependencyFinder.roots());
+
+        // build the qualified exports map
+        Map<String, Set<String>> qualifiedExports =
+            root.exports().entrySet().stream()
+                .filter(e -> !e.getValue().isEmpty())
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toMap(Function.identity(), _k -> new HashSet<>()));
+
+        // adds to the qualified exports map if a module references it
+        for (Module m : exportTargets) {
+            analyzer.dependences(m).stream()
+                    .map(this::toPackageName)
+                    .filter(qualifiedExports::containsKey)
+                    .forEach(pn -> qualifiedExports.get(pn).add(m.name()));
+        }
+
+        // compare with the exports from ModuleDescriptor
+        Set<String> staleQualifiedExports =
+            qualifiedExports.keySet().stream()
+                .filter(pn -> !qualifiedExports.get(pn).equals(root.exports().get(pn)))
+                .collect(Collectors.toSet());
+
+        if (!staleQualifiedExports.isEmpty()) {
+            System.out.println("--- Unused qualified exports in " + root.name());
+            for (String pn : staleQualifiedExports) {
+                Set<String> unused = new HashSet<>(root.exports().get(pn));
+                unused.removeAll(qualifiedExports.get(pn));
+                System.out.format("  exports %s to %s%n", pn,
+                                  unused.stream().collect(Collectors.joining(",")));
+            }
+        }
+    }
+
+    private String toPackageName(String cn) {
+        int i = cn.lastIndexOf('.');
+        return i > 0 ? cn.substring(0, i) : "";
+    }
+
+    private boolean matches(ModuleDescriptor md, Set<String> requires, Set<String> requiresPublic) {
+        Set<String> reqPublic = md.requires().stream()
+                .filter(req -> req.modifiers().contains(PUBLIC))
+                .map(ModuleDescriptor.Requires::name)
+                .collect(Collectors.toSet());
+        if (!requiresPublic.equals(reqPublic)) {
+            trace("mismatch requires public: %s%n", reqPublic);
+            return false;
+        }
+        // java.base is not in requires
+        int javaBase = md.name().equals(JAVA_BASE.name()) ? 0 : 1;
+        if (requires.size()+javaBase != md.requires().size()) {
+            trace("mismatch requires: %d != %d%n", requires.size()+1, md.requires().size());
+            return false;
+        }
+
+        Set<String> unused = md.requires().stream()
+                 .map(ModuleDescriptor.Requires::name)
+                 .filter(req -> !requires.contains(req) && !req.equals(JAVA_BASE.name()))
+                 .collect(Collectors.toSet());
+        if (!unused.isEmpty()) {
+            trace("mismatch requires: %s%n", unused);
+            return false;
+        }
+        return true;
+    }
+
+    private void printModuleDescriptor(PrintStream out, ModuleDescriptor descriptor) {
+        if (descriptor.name().equals("java.base"))
+            return;
+
+        out.format("module %s%n", descriptor.name());
+        descriptor.requires()
+                .stream()
+                .sorted(Comparator.comparing(ModuleDescriptor.Requires::name))
+                .forEach(req -> out.format("  requires %s;%n", req));
+    }
+
+    /**
+     * Returns a graph of modules required by the specified module.
+     *
+     * Requires public edges of the dependences are added to the graph.
+     */
+    private Graph<Module> buildGraph(Analyzer analyzer, Module module) {
+        Graph.Builder<Module> builder = new Graph.Builder<>();
+        builder.addNode(module);
+        Set<Module> visited = new HashSet<>();
+        visited.add(module);
+        Deque<Module> deque = new LinkedList<>();
+        analyzer.requires(module)
+                .map(Archive::getModule)
+                .filter(m -> m != JAVA_BASE)
+                .forEach(m -> {
+                    deque.add(m);
+                    builder.addEdge(module, m);
+                });
+
+        // read requires public from ModuleDescription
+        Module source;
+        while ((source = deque.poll()) != null) {
+            if (visited.contains(source))
+                continue;
+            visited.add(source);
+            builder.addNode(source);
+            Module from = source;
+            source.descriptor().requires().stream()
+                    .filter(req -> req.modifiers().contains(PUBLIC))
+                    .map(ModuleDescriptor.Requires::name)
+                    .map(req -> modulePaths.getModules().get(req))
+                    .filter(m -> m != JAVA_BASE)
+                    .forEach(m -> {
+                        deque.add(m);
+                        builder.addEdge(from, m);
+                    });
+        }
+        return builder.build();
+    }
+
+    static class Graph<T> {
+        private final Set<T> nodes;
+        private final Map<T, Set<T>> edges;
+
+        private Graph(Set<T> nodes, Map<T, Set<T>> edges) {
+            this.nodes = nodes;
+            this.edges = edges;
+        }
+
+        public Set<T> nodes() {
+            return nodes;
+        }
+
+        public Map<T, Set<T>> edges() {
+            return edges;
+        }
+
+        public Set<T> adjacentNodes(T u) {
+            return edges.get(u);
+        }
+
+        /**
+         * Returns a new Graph after transitive reduction
+         */
+        public Graph<T> reduce() {
+            Graph.Builder<T> builder = new Builder<>();
+            nodes.stream()
+                    .forEach(u -> {
+                        builder.addNode(u);
+                        edges.get(u).stream()
+                                .filter(v -> !pathExists(u, v, false))
+                                .forEach(v -> builder.addEdge(u, v));
+                    });
+            return builder.build();
+        }
+
+        /**
+         * Returns a new Graph after transitive reduction.  All edges in
+         * the given g takes precedence over this graph.
+         *
+         * @throw IllegalArgumentException g must be a subgraph this graph
+         */
+        public Graph<T> reduce(Graph<T> g) {
+            boolean subgraph = nodes.containsAll(g.nodes) && g.edges.keySet().stream()
+                    .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u)));
+            if (!subgraph) {
+                throw new IllegalArgumentException(g + " is not a subgraph of " + this);
+            }
+
+            Graph.Builder<T> builder = new Builder<>();
+            nodes.stream()
+                    .forEach(u -> {
+                        builder.addNode(u);
+                        // filter the edge if there exists a path from u to v in the given g
+                        // or there exists another path from u to v in this graph
+                        edges.get(u).stream()
+                                .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false))
+                                .forEach(v -> builder.addEdge(u, v));
+                    });
+
+            // add the overlapped edges from this graph and the given g
+            g.edges().keySet().stream()
+                    .forEach(u -> g.adjacentNodes(u).stream()
+                                    .filter(v -> isAdjacent(u, v))
+                                    .forEach(v -> builder.addEdge(u, v)));
+            return builder.build();
+        }
+
+        /**
+         * Returns nodes sorted in topological order.
+         */
+        public Stream<T> orderedNodes() {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            return sorter.result.stream();
+        }
+
+        /**
+         * Iterates the nodes sorted in topological order and performs the
+         * given action.
+         */
+        public void ordered(Consumer<T> action) {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            sorter.ordered(action);
+        }
+
+        /**
+         * Iterates the nodes sorted in reverse topological order and
+         * performs the given action.
+         */
+        public void reverse(Consumer<T> action) {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            sorter.reverse(action);
+        }
+
+        private boolean isAdjacent(T u, T v) {
+            return edges.containsKey(u) && edges.get(u).contains(v);
+        }
+
+        private boolean pathExists(T u, T v) {
+            return pathExists(u, v, true);
+        }
+
+        /**
+         * Returns true if there exists a path from u to v in this graph.
+         * If includeAdjacent is false, it returns true if there exists
+         * another path from u to v of distance > 1
+         */
+        private boolean pathExists(T u, T v, boolean includeAdjacent) {
+            if (!nodes.contains(u) || !nodes.contains(v)) {
+                return false;
+            }
+            if (includeAdjacent && isAdjacent(u, v)) {
+                return true;
+            }
+            Deque<T> stack = new LinkedList<>();
+            Set<T> visited = new HashSet<>();
+            stack.push(u);
+            while (!stack.isEmpty()) {
+                T node = stack.pop();
+                if (node.equals(v)) {
+                    return true;
+                }
+                if (!visited.contains(node)) {
+                    visited.add(node);
+                    edges.get(node).stream()
+                            .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v))
+                            .forEach(e -> stack.push(e));
+                }
+            }
+            assert !visited.contains(v);
+            return false;
+        }
+
+        void printGraph(PrintStream out) {
+            out.println("graph for " + nodes);
+            nodes.stream()
+                 .forEach(u -> adjacentNodes(u).stream()
+                                   .forEach(v -> out.format("%s -> %s%n", u, v)));
+        }
+
+        @Override
+        public String toString() {
+            return nodes.toString();
+        }
+
+        static class Builder<T> {
+            final Set<T> nodes = new HashSet<>();
+            final Map<T, Set<T>> edges = new HashMap<>();
+
+            public void addNode(T node) {
+                if (nodes.contains(node)) {
+                    return;
+                }
+                nodes.add(node);
+                edges.computeIfAbsent(node, _e -> new HashSet<>());
+            }
+
+            public void addEdge(T u, T v) {
+                addNode(u);
+                addNode(v);
+                edges.get(u).add(v);
+            }
+
+            public Graph<T> build() {
+                return new Graph<>(nodes, edges);
+            }
+
+            void print(PrintStream out) {
+                out.println(nodes);
+                nodes.stream()
+                        .forEach(u -> edges.get(u).stream()
+                                        .forEach(v -> out.format("%s -> %s%n", u, v)));
+            }
+        }
+    }
+
+    static class TopoSorter<T> {
+        final Deque<T> result = new LinkedList<>();
+        final Deque<T> nodes;
+        final Graph<T> graph;
+        TopoSorter(Graph<T> graph) {
+            this.graph = graph;
+            this.nodes = new LinkedList<>(graph.nodes);
+            sort();
+        }
+
+        public void ordered(Consumer<T> action) {
+            result.iterator().forEachRemaining(action);
+        }
+
+        public void reverse(Consumer<T> action) {
+            result.descendingIterator().forEachRemaining(action);
+        }
+
+        private void sort() {
+            Deque<T> visited = new LinkedList<>();
+            Deque<T> done = new LinkedList<>();
+            T node;
+            while ((node = nodes.poll()) != null) {
+                if (!visited.contains(node)) {
+                    visit(node, visited, done);
+                }
+            }
+        }
+
+        private void visit(T node, Deque<T> visited, Deque<T> done) {
+            if (visited.contains(node)) {
+                if (!done.contains(node)) {
+                    throw new IllegalArgumentException("Cyclic detected: " +
+                            node + " " + graph.edges().get(node));
+                }
+                return;
+            }
+            visited.add(node);
+            graph.edges().get(node).stream()
+                 .forEach(x -> visit(x, visited, done));
+            done.add(node);
+            result.addLast(node);
+        }
+    }
+
+    static class DotGraph {
+        static final String ORANGE = "#e76f00";
+        static final String BLUE = "#437291";
+        static final String GRAY = "#dddddd";
+
+        static final String REEXPORTS = "";
+        static final String REQUIRES = "style=\"dashed\"";
+        static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
+
+        static final Set<String> javaModules = modules(name ->
+                (name.startsWith("java.") && !name.equals("java.smartcardio")));
+        static final Set<String> jdkModules = modules(name ->
+                (name.startsWith("java.") ||
+                        name.startsWith("jdk.") ||
+                        name.startsWith("javafx.")) && !javaModules.contains(name));
+
+        private static Set<String> modules(Predicate<String> predicate) {
+            return ModuleFinder.ofSystem().findAll()
+                               .stream()
+                               .map(ModuleReference::descriptor)
+                               .map(ModuleDescriptor::name)
+                               .filter(predicate)
+                               .collect(Collectors.toSet());
+        }
+
+        static void printAttributes(PrintStream out) {
+            out.format("  size=\"25,25\";%n");
+            out.format("  nodesep=.5;%n");
+            out.format("  ranksep=1.5;%n");
+            out.format("  pencolor=transparent;%n");
+            out.format("  node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n");
+            out.format("  edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n");
+        }
+
+        static void printNodes(PrintStream out, Graph<String> graph) {
+            out.format("  subgraph se {%n");
+            graph.nodes().stream()
+                 .filter(javaModules::contains)
+                 .forEach(mn -> out.format("  \"%s\" [fontcolor=\"%s\", group=%s];%n",
+                                           mn, ORANGE, "java"));
+            out.format("  }%n");
+            graph.nodes().stream()
+                 .filter(jdkModules::contains)
+                 .forEach(mn -> out.format("    \"%s\" [fontcolor=\"%s\", group=%s];%n",
+                                              mn, BLUE, "jdk"));
+
+            graph.nodes().stream()
+                    .filter(mn -> !javaModules.contains(mn) && !jdkModules.contains(mn))
+                    .forEach(mn -> out.format("  \"%s\";%n", mn));
+        }
+
+        static void printEdges(PrintStream out, Graph<String> graph,
+                               String node, Set<String> requiresPublic) {
+            graph.adjacentNodes(node).forEach(dn -> {
+                String attr = dn.equals("java.base") ? REQUIRES_BASE
+                        : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES);
+                out.format("  \"%s\" -> \"%s\" [%s];%n", node, dn, attr);
+            });
+        }
+    }
+
+    public void genDotFile(Path dir) throws IOException {
+        String name = root.name();
+        try (PrintStream out
+                     = new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) {
+            Configuration cf = modulePaths.configuration(name);
+
+            // transitive reduction
+            Graph<String> graph = gengraph(cf);
+
+            out.format("digraph \"%s\" {%n", name);
+            DotGraph.printAttributes(out);
+            DotGraph.printNodes(out, graph);
+
+            cf.modules().stream()
+                    .map(ResolvedModule::reference)
+                    .map(ModuleReference::descriptor)
+                    .sorted(Comparator.comparing(ModuleDescriptor::name))
+                    .forEach(md -> {
+                String mn = md.name();
+                Set<String> requiresPublic = md.requires().stream()
+                        .filter(d -> d.modifiers().contains(PUBLIC))
+                        .map(d -> d.name())
+                        .collect(Collectors.toSet());
+
+                DotGraph.printEdges(out, graph, mn, requiresPublic);
+            });
+
+            out.println("}");
+        }
+    }
+
+
+    /**
+     * Returns a Graph of the given Configuration after transitive reduction.
+     *
+     * Transitive reduction of requires public edge and requires edge have
+     * to be applied separately to prevent the requires public edges
+     * (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V)
+     * in which  V would not be re-exported from U.
+     */
+    private Graph<String> gengraph(Configuration cf) {
+        // build a Graph containing only requires public edges
+        // with transitive reduction.
+        Graph.Builder<String> rpgbuilder = new Graph.Builder<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleDescriptor md = resolvedModule.reference().descriptor();
+            String mn = md.name();
+            md.requires().stream()
+                    .filter(d -> d.modifiers().contains(PUBLIC))
+                    .map(d -> d.name())
+                    .forEach(d -> rpgbuilder.addEdge(mn, d));
+        }
+
+        Graph<String> rpg = rpgbuilder.build().reduce();
+
+        // build the readability graph
+        Graph.Builder<String> builder = new Graph.Builder<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleDescriptor md = resolvedModule.reference().descriptor();
+            String mn = md.name();
+            builder.addNode(mn);
+            resolvedModule.reads().stream()
+                    .map(ResolvedModule::name)
+                    .forEach(d -> builder.addEdge(mn, d));
+        }
+
+        // transitive reduction of requires edges
+        return builder.build().reduce(rpg);
+    }
+
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
new file mode 100644
index 0000000..1afed6b
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+package com.sun.tools.jdeps;
+
+import static com.sun.tools.jdeps.Analyzer.Type.CLASS;
+import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
+import static com.sun.tools.jdeps.Module.trace;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ModuleInfoBuilder {
+    final ModulePaths modulePaths;
+    final DependencyFinder dependencyFinder;
+    final JdepsFilter filter;
+    final Analyzer analyzer;
+    final Map<Module, Module> strictModules = new HashMap<>();
+    ModuleInfoBuilder(ModulePaths modulePaths, DependencyFinder finder) {
+        this.modulePaths = modulePaths;
+        this.dependencyFinder = finder;
+        this.filter = new JdepsFilter.Builder().filter(true, true).build();
+        this.analyzer = new Analyzer(CLASS, filter);
+    }
+
+    private Stream<Module> automaticModules() {
+        return modulePaths.getModules().values()
+                .stream()
+                .filter(Module::isAutomatic);
+    }
+
+    /**
+     * Compute 'requires public' dependences by analyzing API dependencies
+     */
+    Map<Module, Set<Module>> computeRequiresPublic() throws IOException {
+        dependencyFinder.findDependencies(filter, true /* api only */, 1);
+        Analyzer pass1 = new Analyzer(Analyzer.Type.CLASS, filter);
+
+        pass1.run(dependencyFinder.archives());
+
+        return automaticModules().collect(Collectors.toMap(Function.identity(),
+                source -> pass1.requires(source)
+                               .map(Archive::getModule)
+                               .collect(Collectors.toSet())));
+    }
+
+    boolean run(Analyzer.Type verbose, boolean quiet) throws IOException {
+        // add all automatic modules to the root set
+        automaticModules().forEach(dependencyFinder::addRoot);
+
+        // pass 1: find API dependencies
+        Map<Module, Set<Module>> requiresPublic = computeRequiresPublic();
+
+        // pass 2: analyze all class dependences
+        dependencyFinder.findDependencies(filter, false /* all classes */, 1);
+        analyzer.run(dependencyFinder.archives());
+
+        // computes requires and requires public
+        automaticModules().forEach(m -> {
+            Map<String, Boolean> requires;
+            if (requiresPublic.containsKey(m)) {
+                requires = requiresPublic.get(m)
+                        .stream()
+                        .collect(Collectors.toMap(Archive::getName, (v) -> Boolean.TRUE));
+            } else {
+                requires = new HashMap<>();
+            }
+            analyzer.requires(m)
+                    .forEach(d -> requires.putIfAbsent(d.getName(), Boolean.FALSE));
+
+            trace("strict module %s requires %s%n", m.name(), requires);
+            strictModules.put(m, m.toStrictModule(requires));
+        });
+
+        // find any missing dependences
+        Optional<Module> missingDeps = automaticModules()
+                .filter(this::missingDep)
+                .findAny();
+        if (missingDeps.isPresent()) {
+            automaticModules()
+                    .filter(this::missingDep)
+                    .forEach(m -> {
+                        System.err.format("Missing dependencies from %s%n", m.name());
+                        analyzer.visitDependences(m,
+                                new Analyzer.Visitor() {
+                                    @Override
+                                    public void visitDependence(String origin, Archive originArchive,
+                                                                String target, Archive targetArchive) {
+                                        if (targetArchive == NOT_FOUND)
+                                            System.err.format("   %-50s -> %-50s %s%n",
+                                                    origin, target, targetArchive.getName());
+                                    }
+                                }, verbose);
+                        System.err.println();
+                    });
+
+            System.err.println("ERROR: missing dependencies (check \"requires NOT_FOUND;\")");
+        }
+        return missingDeps.isPresent() ? false : true;
+    }
+
+    private boolean missingDep(Archive m) {
+        return analyzer.requires(m).filter(a -> a.equals(NOT_FOUND))
+                       .findAny().isPresent();
+    }
+
+    void build(Path dir) throws IOException {
+        ModuleInfoWriter writer = new ModuleInfoWriter(dir);
+        writer.generateOutput(strictModules.values(), analyzer);
+    }
+
+    private class ModuleInfoWriter {
+        private final Path outputDir;
+        ModuleInfoWriter(Path dir) {
+            this.outputDir = dir;
+        }
+
+        void generateOutput(Iterable<Module> modules, Analyzer analyzer) throws IOException {
+            // generate module-info.java file for each archive
+            for (Module m : modules) {
+                if (m.packages().contains("")) {
+                    System.err.format("ERROR: %s contains unnamed package.  " +
+                                      "module-info.java not generated%n", m.getPathName());
+                    continue;
+                }
+
+                String mn = m.getName();
+                Path srcFile = outputDir.resolve(mn).resolve("module-info.java");
+                Files.createDirectories(srcFile.getParent());
+                System.out.println("writing to " + srcFile);
+                try (PrintWriter pw = new PrintWriter(Files.newOutputStream(srcFile))) {
+                    printModuleInfo(pw, m);
+                }
+            }
+        }
+
+        private void printModuleInfo(PrintWriter writer, Module m) {
+            writer.format("module %s {%n", m.name());
+
+            Map<String, Module> modules = modulePaths.getModules();
+            Map<String, Boolean> requires = m.requires();
+            // first print the JDK modules
+            requires.keySet().stream()
+                    .filter(mn -> !mn.equals("java.base"))   // implicit requires
+                    .filter(mn -> modules.containsKey(mn) && modules.get(mn).isJDK())
+                    .sorted()
+                    .forEach(mn -> {
+                        String modifier = requires.get(mn) ? "public " : "";
+                        writer.format("    requires %s%s;%n", modifier, mn);
+                    });
+
+            // print requires non-JDK modules
+            requires.keySet().stream()
+                    .filter(mn -> !modules.containsKey(mn) || !modules.get(mn).isJDK())
+                    .sorted()
+                    .forEach(mn -> {
+                        String modifier = requires.get(mn) ? "public " : "";
+                        writer.format("    requires %s%s;%n", modifier, mn);
+                    });
+
+            m.packages().stream()
+                    .sorted()
+                    .forEach(pn -> writer.format("    exports %s;%n", pn));
+
+            m.provides().entrySet().stream()
+                    .sorted(Map.Entry.comparingByKey())
+                    .forEach(e -> {
+                        String service = e.getKey();
+                        e.getValue().stream()
+                                .sorted()
+                                .forEach(impl -> writer.format("    provides %s with %s;%n", service, impl));
+                    });
+
+            writer.println("}");
+        }
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java
new file mode 100644
index 0000000..8e1cdb8
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeps;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+public class ModulePaths {
+    final ModuleFinder finder;
+    final Map<String, Module> modules = new LinkedHashMap<>();
+
+    public ModulePaths(String upgradeModulePath, String modulePath) {
+        this(upgradeModulePath, modulePath, Collections.emptyList());
+    }
+
+    public ModulePaths(String upgradeModulePath, String modulePath, List<Path> jars) {
+        ModuleFinder finder = ModuleFinder.ofSystem();
+        if (upgradeModulePath != null) {
+            finder = ModuleFinder.compose(createModulePathFinder(upgradeModulePath), finder);
+        }
+        if (jars.size() > 0) {
+            finder = ModuleFinder.compose(finder, ModuleFinder.of(jars.toArray(new Path[0])));
+        }
+        if (modulePath != null) {
+            finder = ModuleFinder.compose(finder, createModulePathFinder(modulePath));
+        }
+        this.finder = finder;
+
+        // add modules from modulepaths
+        finder.findAll().stream().forEach(mref ->
+            modules.computeIfAbsent(mref.descriptor().name(), mn -> toModule(mn, mref))
+        );
+    }
+
+    /**
+     * Returns the list of Modules that can be found in the specified
+     * module paths.
+     */
+    Map<String, Module> getModules() {
+        return modules;
+    }
+
+    Set<Module> dependences(String... roots) {
+        Configuration cf = configuration(roots);
+        return cf.modules().stream()
+                .map(ResolvedModule::name)
+                .map(modules::get)
+                .collect(Collectors.toSet());
+    }
+
+    Configuration configuration(String... roots) {
+        return Configuration.empty().resolveRequires(finder, ModuleFinder.empty(), Set.of(roots));
+    }
+
+    private static ModuleFinder createModulePathFinder(String mpaths) {
+        if (mpaths == null) {
+            return null;
+        } else {
+            String[] dirs = mpaths.split(File.pathSeparator);
+            Path[] paths = new Path[dirs.length];
+            int i = 0;
+            for (String dir : dirs) {
+                paths[i++] = Paths.get(dir);
+            }
+            return ModuleFinder.of(paths);
+        }
+    }
+
+    private static Module toModule(String mn, ModuleReference mref) {
+        return SystemModulePath.find(mn)
+                               .orElse(toModule(new Module.Builder(mn), mref));
+    }
+
+    private static Module toModule(Module.Builder builder, ModuleReference mref) {
+        ModuleDescriptor md = mref.descriptor();
+        builder.descriptor(md);
+        for (ModuleDescriptor.Requires req : md.requires()) {
+            builder.require(req.name(), req.modifiers().contains(PUBLIC));
+        }
+        for (ModuleDescriptor.Exports exp : md.exports()) {
+            builder.export(exp.source(), exp.targets());
+        }
+        builder.packages(md.packages());
+
+        try {
+            URI location = mref.location()
+                               .orElseThrow(FileNotFoundException::new);
+            builder.location(location);
+            builder.classes(getClassReader(location, md.name()));
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return builder.build();
+    }
+
+    static class SystemModulePath {
+        final static Module JAVA_BASE;
+
+        private final static FileSystem fs;
+        private final static Path root;
+        private final static Map<String, Module> installed = new HashMap<>();
+        static {
+            if (isJrtAvailable()) {
+                // jrt file system
+                fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+                root = fs.getPath("/modules");
+            } else {
+                // exploded image
+                String javahome = System.getProperty("java.home");
+                fs = FileSystems.getDefault();
+                root = Paths.get(javahome, "modules");
+            }
+
+            ModuleFinder.ofSystem().findAll().stream()
+                 .forEach(mref ->
+                     installed.computeIfAbsent(mref.descriptor().name(),
+                                               mn -> toModule(new Module.Builder(mn, true), mref))
+                 );
+            JAVA_BASE = installed.get("java.base");
+
+            Profile.init(installed);
+        }
+
+        private static boolean isJrtAvailable() {
+            try {
+                FileSystems.getFileSystem(URI.create("jrt:/"));
+                return true;
+            } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
+                return false;
+            }
+        }
+
+        public static Optional<Module> find(String mn) {
+            return installed.containsKey(mn) ? Optional.of(installed.get(mn))
+                                             : Optional.empty();
+        }
+
+        public static boolean contains(Module m) {
+            return installed.containsValue(m);
+        }
+
+        public static ClassFileReader getClassReader(String modulename) throws IOException {
+            Path mp = root.resolve(modulename);
+            if (Files.exists(mp) && Files.isDirectory(mp)) {
+                return ClassFileReader.newInstance(fs, mp);
+            } else {
+                throw new FileNotFoundException(mp.toString());
+            }
+        }
+    }
+
+    /**
+     * Returns a ModuleClassReader that only reads classes for the given modulename.
+     */
+    public static ClassFileReader getClassReader(URI location, String modulename)
+            throws IOException {
+        if (location.getScheme().equals("jrt")) {
+            return SystemModulePath.getClassReader(modulename);
+        } else {
+            Path path = Paths.get(location);
+            return ClassFileReader.newInstance(path);
+        }
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java
deleted file mode 100644
index be9d3d3..0000000
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.jdeps;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.Set;
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.XMLEvent;
-import com.sun.tools.jdeps.ClassFileReader.ModuleClassReader;
-import com.sun.tools.jdeps.PlatformClassPath.ImageHelper;
-
-final class ModulesXmlReader {
-    public static Set<Module> load(ImageHelper helper,InputStream in)
-        throws IOException
-    {
-        try {
-            ModulesXmlReader reader = new ModulesXmlReader(helper);
-            return reader.load(in);
-        } catch (XMLStreamException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static final String MODULES   = "modules";
-    private static final String MODULE    = "module";
-    private static final String NAME      = "name";
-    private static final String DEPEND    = "depend";
-    private static final String EXPORT    = "export";
-    private static final String TO        = "to";
-    private static final QName  REEXPORTS = new QName("re-exports");
-    private final ImageHelper helper;
-    ModulesXmlReader(ImageHelper helper) {
-        this.helper = helper;
-    }
-
-    public Set<Module> load(InputStream in) throws XMLStreamException, IOException {
-        Set<Module> modules = new HashSet<>();
-        if (in == null) {
-            throw new RuntimeException("jdeps-modules.xml doesn't exist");
-        }
-        XMLInputFactory factory = XMLInputFactory.newInstance();
-        XMLEventReader reader = factory.createXMLEventReader(in, "UTF-8");
-        Module.Builder mb = null;
-        String modulename = null;
-        String exportedPackage = null;
-        Set<String> permits = new HashSet<>();
-        while (reader.hasNext()) {
-            XMLEvent event = reader.nextEvent();
-            if (event.isStartElement()) {
-                String startTag = event.asStartElement().getName().getLocalPart();
-                switch (startTag) {
-                    case MODULES:
-                        break;
-                    case MODULE:
-                        if (mb != null) {
-                            throw new RuntimeException("end tag for module is missing");
-                        }
-                        modulename = getNextTag(reader, NAME);
-                        mb = new Module.Builder();
-                        mb.name(modulename);
-                        break;
-                    case NAME:
-                        throw new RuntimeException(event.toString());
-                    case DEPEND:
-                        boolean reexports = false;
-                        Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
-                        if (attr != null) {
-                            String value = attr.getValue();
-                            if (value.equals("true") || value.equals("false")) {
-                                reexports = Boolean.parseBoolean(value);
-                            } else {
-                                throw new RuntimeException("unexpected attribute " + attr.toString());
-                            }
-                        }
-                        mb.require(getData(reader), reexports);
-                        break;
-                    case EXPORT:
-                        exportedPackage = getNextTag(reader, NAME);
-                        break;
-                    case TO:
-                        permits.add(getData(reader));
-                        break;
-                    default:
-                        throw new RuntimeException("invalid element: " + event);
-                }
-            } else if (event.isEndElement()) {
-                String endTag = event.asEndElement().getName().getLocalPart();
-                switch (endTag) {
-                    case MODULE:
-                        ModuleClassReader cfr = helper.getModuleClassReader(modulename);
-                        mb.classes(cfr);
-                        mb.packages(cfr.packages());
-                        modules.add(mb.build());
-                        mb = null;
-                        break;
-                    case EXPORT:
-                        if (exportedPackage == null) {
-                            throw new RuntimeException("export's name is missing");
-                        }
-                        mb.export(exportedPackage, permits);
-                        exportedPackage = null;
-                        permits.clear();
-                        break;
-                    default:
-                }
-            } else if (event.isCharacters()) {
-                String s = event.asCharacters().getData();
-                if (!s.trim().isEmpty()) {
-                    throw new RuntimeException("export-to is malformed");
-                }
-            }
-        }
-        return modules;
-    }
-    private String getData(XMLEventReader reader) throws XMLStreamException {
-        XMLEvent e = reader.nextEvent();
-        if (e.isCharacters()) {
-            return e.asCharacters().getData();
-        }
-        throw new RuntimeException(e.toString());
-    }
-
-    private String getNextTag(XMLEventReader reader, String tag) throws XMLStreamException {
-        XMLEvent e = reader.nextTag();
-        if (e.isStartElement()) {
-            String t = e.asStartElement().getName().getLocalPart();
-            if (!tag.equals(t)) {
-                throw new RuntimeException(e + " expected: " + tag);
-            }
-            return getData(reader);
-        }
-        throw new RuntimeException("export-to name is missing:" + e);
-    }
-}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
deleted file mode 100644
index 6142b4b..0000000
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.jdeps;
-
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.jdeps.ClassFileReader.ModuleClassReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.BufferedInputStream;
-import java.net.URI;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * ClassPath for Java SE and JDK
- */
-class PlatformClassPath {
-    private static List<Archive> modules;
-    static synchronized List<Archive> getModules(Path mpath) throws IOException {
-        if (modules == null) {
-            initPlatformModules(mpath);
-        }
-        return modules;
-    }
-
-    private static void initPlatformModules(Path mpath) throws IOException {
-        ImageHelper helper = ImageHelper.getInstance(mpath);
-        String fn = System.getProperty("jdeps.modules.xml");
-        if (fn != null) {
-            Path p = Paths.get(fn);
-            try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) {
-                modules = new ArrayList<>(ModulesXmlReader.load(helper, in));
-            }
-        } else {
-            try (InputStream in = PlatformClassPath.class
-                    .getResourceAsStream("resources/jdeps-modules.xml")) {
-                modules = new ArrayList<>(ModulesXmlReader.load(helper, in));
-            }
-        }
-        if (findModule("java.base") != null) {
-            Profile.initProfiles(modules);
-        }
-    }
-
-    /**
-     * Finds the module with the given name. Returns null
-     * if such module doesn't exist.
-     *
-     * @param mn module name
-     */
-    static Module findModule(String mn) {
-        for (Archive a : modules) {
-            if (Module.class.isInstance(a)) {
-                Module m = (Module)a;
-                if (mn.equals(m.name())) {
-                    return m;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns JAR files in $java.home/lib.  This is for transition until
-     * all components are linked into jimage.
-     */
-    static List<Archive> getJarFiles() throws IOException {
-        Path home = Paths.get(System.getProperty("java.home"), "lib");
-        return Files.find(home, 1, (Path p, BasicFileAttributes attr)
-                -> p.getFileName().toString().endsWith(".jar"))
-                .map(Archive::getInstance)
-                .collect(Collectors.toList());
-    }
-
-    static class ImageHelper {
-        private static boolean isJrtAvailable() {
-            try {
-                FileSystems.getFileSystem(URI.create("jrt:/"));
-                return true;
-            } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
-                return false;
-            }
-        }
-
-        static ImageHelper getInstance(Path mpath) throws IOException {
-            if (mpath != null) {
-                return new ImageHelper(mpath);
-            }
-
-            if (isJrtAvailable()) {
-                // jrt file system
-                FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-                return new ImageHelper(fs, fs.getPath("/modules"));
-            } else {
-                // exploded modules
-                String home = System.getProperty("java.home");
-                Path exploded = Paths.get(home, "modules");
-                if (!Files.isDirectory(exploded)) {
-                     throw new InternalError(home + " not a modular image");
-                }
-                return new ImageHelper(exploded);
-            }
-        }
-
-        private final FileSystem fs;
-        private final Path mpath;
-
-        ImageHelper(Path path) throws IOException {
-            this(FileSystems.getDefault(), path);
-        }
-
-        ImageHelper(FileSystem fs, Path path) throws IOException {
-            this.fs = fs;
-            this.mpath = path;
-        }
-
-        /**
-         * Returns a ModuleClassReader that only reads classes for the given modulename.
-         */
-        public ModuleClassReader getModuleClassReader(String modulename)
-            throws IOException
-        {
-            Path mp = mpath.resolve(modulename);
-            if (Files.exists(mp) && Files.isDirectory(mp)) {
-                return new ModuleClassReader(fs, modulename, mp);
-            } else {
-                // aggregator module or os-specific module in jdeps-modules.xml
-                // mdir not exist
-                return new NonExistModuleReader(fs, modulename, mp);
-            }
-        }
-
-        static class NonExistModuleReader extends ModuleClassReader {
-            private final List<ClassFile> classes = Collections.emptyList();
-
-            private NonExistModuleReader(FileSystem fs, String mn, Path mpath)
-                throws IOException
-            {
-                super(fs, mn, mpath);
-            }
-
-            public ClassFile getClassFile(String name) throws IOException {
-                return null;
-            }
-
-            public Iterable<ClassFile> getClassFiles() throws IOException {
-                return classes;
-            }
-
-            public Set<String> packages() {
-                return Collections.emptySet();
-            }
-        }
-    }
-}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java
index 1c45a2f..c0790ab 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,7 +26,10 @@
 package com.sun.tools.jdeps;
 
 import java.io.IOException;
-import java.util.*;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Build the profile information.
@@ -38,7 +41,12 @@
                             "jdk.httpserver", "jdk.security.auth",
                             "jdk.naming.dns", "jdk.naming.rmi",
                             "jdk.management"),
-    FULL_JRE("Full JRE", 4, "java.se", "jdk.charsets",
+    // need a way to determine JRE modules
+    SE_JRE("Java SE JRE", 4, "java.se", "jdk.charsets",
+                            "jdk.crypto.ec", "jdk.crypto.pkcs11",
+                            "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat",
+                            "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"),
+    FULL_JRE("Full JRE", 5, "java.se.ee", "jdk.charsets",
                             "jdk.crypto.ec", "jdk.crypto.pkcs11",
                             "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat",
                             "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs");
@@ -94,25 +102,27 @@
     }
 
     private final static Set<Module> JDK = new HashSet<>();
-    static void initProfiles(List<Archive> modules) {
-        // add all modules into  JDK
-        modules.forEach(m -> JDK.add((Module)m));
-
+    static synchronized void init(Map<String, Module> installed) {
         for (Profile p : Profile.values()) {
             for (String mn : p.mnames) {
                 // this includes platform-dependent module that may not exist
-                Module m = PlatformClassPath.findModule(mn);
+                Module m = installed.get(mn);
                 if (m != null) {
-                    p.addModule(m);
+                    p.addModule(installed, m);
                 }
             }
         }
+
+        // JDK modules should include full JRE plus other jdk.* modules
+        // Just include all installed modules.  Assume jdeps is running
+        // in JDK image
+        JDK.addAll(installed.values());
     }
 
-    private void addModule(Module m) {
+    private void addModule(Map<String, Module> installed, Module m) {
         modules.add(m);
         for (String n : m.requires().keySet()) {
-            Module d = PlatformClassPath.findModule(n);
+            Module d = installed.get(n);
             if (d == null) {
                 throw new InternalError("module " + n + " required by " +
                         m.name() + " doesn't exist");
@@ -123,7 +133,6 @@
     // for debugging
     public static void main(String[] args) throws IOException {
         // find platform modules
-        PlatformClassPath.getModules(null);
         if (Profile.getProfileCount() == 0) {
             System.err.println("No profile is present in this JDK");
         }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
index 5da8667..b0fc19b 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
@@ -1,99 +1,146 @@
 main.usage.summary=\
-Usage: {0} <options> <classes...>\n\
+Usage: {0} <options> [-m <module-name> | <classes...>]\n\
 use -h, -? or -help for a list of possible options
 
 main.usage=\
-Usage: {0} <options> <classes...>\n\
-where <classes> can be a pathname to a .class file, a directory, a JAR file,\n\
-or a fully-qualified class name.  Possible options include:
+Usage: {0} <options> [-m <module-name> | <classes...>]\n\
+If -m <module-name> is specified, the specified module will be analyzed\n\
+otherwise, <classes> can be a pathname to a .class file, a directory,\n\
+a JAR file, or a fully-qualified class name.\n\
+\n\
+Possible options include:
 
 error.prefix=Error:
 warn.prefix=Warning:
 
 main.opt.h=\
-\  -h -?        -help                 Print this usage message
+\  -h -?        -help                   Print this usage message
 
 main.opt.version=\
-\  -version                           Version information
+\  -version                             Version information
 
 main.opt.v=\
-\  -v           -verbose              Print all class level dependencies\n\
-\                                     Equivalent to -verbose:class -filter:none.\n\
-\  -verbose:package                   Print package-level dependencies excluding\n\
-\                                     dependencies within the same package by default\n\
-\  -verbose:class                     Print class-level dependencies excluding\n\
-\                                     dependencies within the same package by default
+\  -v           -verbose                Print all class level dependencies\n\
+\                                       Equivalent to -verbose:class -filter:none.\n\
+\  -verbose:package                     Print package-level dependencies excluding\n\
+\                                       dependencies within the same package by default\n\
+\  -verbose:class                       Print class-level dependencies excluding\n\
+\                                       dependencies within the same package by default
 
 main.opt.f=\
-\  -f <regex>   -filter <regex>       Filter dependences matching the given pattern\n\
-\                                     If given multiple times, the last one will be used.\n\
-\  -filter:package                    Filter dependences within the same package (default)\n\
-\  -filter:archive                    Filter dependences within the same archive\n\
-\  -filter:none                       No -filter:package and -filter:archive filtering\n\
-\                                     Filtering specified via the -filter option still applies.
+\  -f <regex>  -filter <regex>          Filter dependences matching the given pattern\n\
+\                                       If given multiple times, the last one will be used.\n\
+\  -filter:package                      Filter dependences within the same package (default)\n\
+\  -filter:module                       Filter dependences within the same module\n\
+\  -filter:archive                      Filter dependences within the same archive\n\
+\  -filter:none                         No -filter:package and -filter:archive filtering\n\
+\                                       Filtering specified via the -filter option still applies.
 
 main.opt.s=\
-\  -s           -summary              Print dependency summary only
+\  -s           -summary                Print dependency summary only.\n\
+\                                       If -s option is used with -m, the module descriptor of\n\
+\                                       the given module will be read to generate the graph.
 
 main.opt.p=\
-\  -p <pkgname> -package <pkgname>    Finds dependences matching the given package name\n\
-\                                     (may be given multiple times)
+\  -p <pkgname>                         Finds dependences matching the given package name\n\
+\  -package <pkgname>                   (may be given multiple times).
 
 main.opt.e=\
-\  -e <regex>   -regex <regex>        Finds dependences matching the given pattern\n\
-\                                     (-p and -e are exclusive)
+\  -e <regex>\n\
+\  -regex <regex>                       Finds dependences matching the given pattern.
+
+main.opt.module=\
+\  -module <module-name>                Finds dependences matching the given module name\n\
+\                                       (may be given multiple times).\n\
+\                                       -package, -regex, -requires are mutual exclusive.
 
 main.opt.include=\
-\  -include <regex>                   Restrict analysis to classes matching pattern\n\
-\                                     This option filters the list of classes to\n\
-\                                     be analyzed.  It can be used together with\n\
-\                                     -p and -e which apply pattern to the dependences
+\  -include <regex>                     Restrict analysis to classes matching pattern\n\
+\                                       This option filters the list of classes to\n\
+\                                       be analyzed.  It can be used together with\n\
+\                                       -p and -e which apply pattern to the dependences
 
 main.opt.P=\
-\  -P           -profile              Show profile or the file containing a package
+\  -P           -profile                Show profile containing a package
 
 main.opt.M=\
-\  -M           -module               Show module containing the package
+\  -M                                   Show module containing a package
 
 main.opt.cp=\
-\  -cp <path>   -classpath <path>     Specify where to find class files
+\  -cp <path>   -classpath <path>       Specify where to find class files
+
+main.opt.mp=\
+\  -mp <module path>...\n\
+\  -modulepath <module path>...         Specify module path
+
+main.opt.upgrademodulepath=\
+\  -upgrademodulepath <module path>...  Specify upgrade module path
+
+main.opt.m=\
+\  -m <module-name>                     Specify the name of the module and its transitive\n\
+\                                       dependences to be analyzed.
 
 main.opt.R=\
-\  -R           -recursive            Recursively traverse all dependencies.\n\
-\                                     The -R option implies -filter:none.  If -p, -e, -f\n\
-\                                     option is specified, only the matching dependences\n\
-\                                     are analyzed.
+\  -R           -recursive              Recursively traverse all run-time dependencies.\n\
+\                                       The -R option implies -filter:none.  If -p, -e, -f\n\
+\                                       option is specified, only the matching dependences\n\
+\                                       are analyzed.
+
+main.opt.ct=\
+\  -ct          -compile-time           Compile-time view of transitive dependencies\n\
+\                                       i.e. compile-time view of -R option.  If a dependence\n\
+\                                       is found from a directory, a JAR file or a module,\n\
+\                                       all class files in that containing archive are analyzed.
 
 main.opt.apionly=\
-\  -apionly                           Restrict analysis to APIs i.e. dependences\n\
-\                                     from the signature of public and protected\n\
-\                                     members of public classes including field\n\
-\                                     type, method parameter types, returned type,\n\
-\                                     checked exception types etc
+\  -apionly                             Restrict analysis to APIs i.e. dependences\n\
+\                                       from the signature of public and protected\n\
+\                                       members of public classes including field\n\
+\                                       type, method parameter types, returned type,\n\
+\                                       checked exception types etc
+
+main.opt.genmoduleinfo=\
+\  -genmoduleinfo <dir>                 Generate module-info.java under the specified directory.\n\
+\                                       The specified JAR files will be analyzed.\n\
+\                                       This option cannot be used with -dotoutput or -cp.
+
+main.opt.check=\
+\  -check                               Analyze the dependence of a given module specified via\n\
+\                                       -m option.  It prints out the resulting module dependency\n\
+\                                       graph after transition reduction and also identifies any\n\
+\                                       unused qualified exports.
+
 
 main.opt.dotoutput=\
-\  -dotoutput <dir>                   Destination directory for DOT file output
+\  -dotoutput <dir>                     Destination directory for DOT file output
 
 main.opt.jdkinternals=\
-\  -jdkinternals                      Finds class-level dependences on JDK internal APIs.\n\
-\                                     By default, it analyzes all classes on -classpath\n\
-\                                     and input files unless -include option is specified.\n\
-\                                     This option cannot be used with -p, -e and -s options.\n\
-\                                     WARNING: JDK internal APIs may not be accessible in\n\
-\                                     the next release.
+\  -jdkinternals                        Finds class-level dependences on JDK internal APIs.\n\
+\                                       By default, it analyzes all classes on -classpath\n\
+\                                       and input files unless -include option is specified.\n\
+\                                       This option cannot be used with -p, -e and -s options.\n\
+\                                       WARNING: JDK internal APIs may not be accessible in\n\
+\                                       the next release.
 
 main.opt.depth=\
-\  -depth=<depth>                     Specify the depth of the transitive\n\
-\                                     dependency analysis
+\  -depth=<depth>                       Specify the depth of the transitive\n\
+\                                       dependency analysis
 
+main.opt.q=\
+\  -q           -quiet                  Do not show missing dependencies from -genmoduleinfo output.
 
 err.unknown.option=unknown option: {0}
 err.missing.arg=no value given for {0}
 err.invalid.arg.for.option=invalid argument for option: {0}
 err.option.after.class=option must be specified before classes: {0}
-err.option.unsupported={0} not supported: {1}
+err.genmoduleinfo.not.jarfile={0} not valid for -genmoduleinfo option (must be JAR file)
 err.profiles.msg=No profile information
+err.exception.message={0}
 err.invalid.path=invalid path: {0}
+err.invalid.module.option=-m {0} is set but {1} is specified.
+err.invalid.filters=Only one of -package (-p), -regex (-e), -requires option can be set
+err.module.not.found=module not found: {0}
+err.root.module.not.set=-m is not set
 warn.invalid.arg=Invalid classname or pathname not exist: {0}
 warn.split.package=package {0} defined in {1} {2}
 warn.replace.useJDKInternals=\
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
index 56d7d0a..6dd8380 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
@@ -3,6 +3,7 @@
 com.sun.image.codec=Use javax.imageio @since 1.4
 com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6
 com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8
+com.sun.org.apache.xml.internal.resolver=Use javax.xml.catalog @since 9
 com.sun.net.ssl=Use javax.net.ssl @since 1.4
 com.sun.net.ssl.internal.ssl.Provider=Use java.security.Security.getProvider(provider-name) @since 1.3
 com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7
@@ -11,7 +12,7 @@
 sun.awt.image.codec=Use javax.imageio @since 1.4
 sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8
 sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8
-sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2
+sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
 sun.misc.Service=Use java.util.ServiceLoader @since 1.6
 sun.security.action=Use java.security.PrivilegedAction @since 1.1
 sun.security.krb5=Use com.sun.security.jgss
@@ -20,3 +21,5 @@
 sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1
 sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
 sun.tools.jar=Use java.util.jar or jar tool @since 1.2
+jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
+
diff --git a/langtools/src/jdk.jdeps/share/classes/module-info.java b/langtools/src/jdk.jdeps/share/classes/module-info.java
new file mode 100644
index 0000000..7a1f730
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jdeps {
+    requires java.base;
+    requires java.compiler;
+    requires jdk.compiler;
+    exports com.sun.tools.classfile to
+        jdk.jlink;
+}
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
index 5ac073b..1a0cec3 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
@@ -113,6 +113,8 @@
                     }
                     Method doitMethod;
                     try {
+                        this.getClass().getModule().addReads(klass.getModule());
+                        this.getClass().getModule().addExports(RemoteResolutionException.class.getPackage().getName(), klass.getModule());
                         doitMethod = klass.getDeclaredMethod(DOIT_METHOD_NAME, new Class<?>[0]);
                         doitMethod.setAccessible(true);
                         Object res;
@@ -182,6 +184,7 @@
                         break;
                     }
                     try {
+                        this.getClass().getModule().addReads(klass.getModule());
                         Field var = klass.getDeclaredField(varname);
                         var.setAccessible(true);
                         Object res = var.get(null);
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java
index 8f629fd..abaa5cb 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java
@@ -257,8 +257,7 @@
 
         String connectorName = "com.sun.jdi.CommandLineLaunch";
         String classPath = System.getProperty("java.class.path");
-        String bootclassPath = System.getProperty("sun.boot.class.path");
-        String javaArgs = "-classpath \"" + classPath + "\" -Xbootclasspath:\"" + bootclassPath + "\"";
+        String javaArgs = "-classpath " + classPath;
         Map<String, String> argumentName2Value = new HashMap<>();
         argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port);
         argumentName2Value.put("options", javaArgs);
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
index 2fbb46a..c7be108 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
@@ -657,7 +657,7 @@
     private PackageElement createPackageElement(AnalyzeTask at, String packageName) {
         Names names = Names.instance(at.getContext());
         Symtab syms = Symtab.instance(at.getContext());
-        PackageElement existing = syms.enterPackage(names.fromString(packageName));
+        PackageElement existing = syms.enterPackage(syms.unnamedModule, names.fromString(packageName));
 
         return existing;
     }
@@ -1297,7 +1297,7 @@
     }
 
     static boolean isJRTMarkerFile(Path path) {
-        return path.equals(Paths.get("JRT_MARKER_FILE"));
+        return path.equals(Paths.get(System.getProperty("java.home"), "lib", "modules"));
     }
 
     //create an index based on the content of the given dirs; the original JavaFileManager entry is originalPath.
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
index f27b0c7..8ad7862 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
@@ -249,7 +249,7 @@
 
         AnalyzeTask(final Collection<Unit> units) {
             this(units.stream(), new UnitSourceHandler(),
-                    "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-proc:none");
+                    "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none");
         }
 
         <T>AnalyzeTask(final Stream<T> stream, SourceHandler<T> sourceHandler,
@@ -291,7 +291,7 @@
 
         CompileTask(Collection<Unit> units) {
             super(units.stream(), new UnitSourceHandler(),
-                    "-Xlint:unchecked", "-proc:none");
+                    "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none");
         }
 
         boolean compile() {
diff --git a/langtools/src/jdk.jshell/share/classes/module-info.java b/langtools/src/jdk.jshell/share/classes/module-info.java
new file mode 100644
index 0000000..93b16ba
--- /dev/null
+++ b/langtools/src/jdk.jshell/share/classes/module-info.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jshell {
+    requires public java.compiler;
+    requires java.desktop;
+    requires java.prefs;
+    requires jdk.compiler;
+    requires jdk.internal.le;
+    requires jdk.jdi;
+
+    exports jdk.jshell;
+}