changeset 2967:aa22f1ec8ded

Merge
author mchung
date Thu, 02 Apr 2015 18:57:23 -0700
parents 448dc7c4756d b9ceb92798bf
children 31fd9957342a
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
diffstat 97 files changed, 6765 insertions(+), 407 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Mar 30 16:38:59 2015 +0100
+++ b/.hgignore	Thu Apr 02 18:57:23 2015 -0700
@@ -5,3 +5,4 @@
 /nbproject/private/
 ^.hgtip
 .DS_Store
+^src_shuffled/
--- a/.jcheck/conf	Mon Mar 30 16:38:59 2015 +0100
+++ b/.jcheck/conf	Thu Apr 02 18:57:23 2015 -0700
@@ -1,1 +1,3 @@
 project=jdk9
+comments=lax
+tags=lax
--- a/make/CompileInterim.gmk	Mon Mar 30 16:38:59 2015 +0100
+++ b/make/CompileInterim.gmk	Thu Apr 02 18:57:23 2015 -0700
@@ -48,6 +48,9 @@
       $(SUPPORT_OUTPUTDIR)/gensrc/jdk.dev \
       $(SUPPORT_OUTPUTDIR)/gensrc/jdk.javadoc, \
     EXCLUDES := sun jdk, \
+    EXCLUDE_FILES := $(LANGTOOLS_TOPDIR)/src/java.compiler/share/classes/module-info.java \
+      $(LANGTOOLS_TOPDIR)/src/jdk.compiler/share/classes/module-info.java \
+      $(LANGTOOLS_TOPDIR)/src/jdk.javadoc/share/classes/module-info.java, \
     COPY := .gif .xml .css .js javax.tools.JavaCompilerTool, \
     BIN := $(BUILDTOOLS_OUTPUTDIR)/langtools_interim_classes, \
     JAR := $(INTERIM_LANGTOOLS_JAR)))
--- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -163,4 +163,16 @@
     public void close() throws IOException {
         fileManager.close();
     }
+
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        return fileManager.getModuleLocation(location, fo, pkgName);
+    }
+
+    public String inferModuleName(Location location) throws IOException {
+        return fileManager.inferModuleName(location);
+    }
+
+    public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        return fileManager.listModuleLocations(location);
+    }
 }
--- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -385,6 +385,7 @@
      * @throws IOException if an I/O error occurred
      * @see #close
      */
+    @Override
     void flush() throws IOException;
 
     /**
@@ -398,5 +399,41 @@
      * @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.
+     */
+    default Location getModuleLocation(Location location, String moduleName) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Gets a location for the module containing a specific file.
+     */
+    default Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Infer the name of the module from its location, as returned by
+     * getModuleLocation or listModuleLocations.
+     * @param location
+     * @return
+     * @throws IOException
+     */
+    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
+     */
+    default Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
 }
--- a/src/java.compiler/share/classes/javax/tools/StandardLocation.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/java.compiler/share/classes/javax/tools/StandardLocation.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, 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
@@ -72,7 +72,27 @@
      * Location of new native header files.
      * @since 1.8
      */
-    NATIVE_HEADER_OUTPUT;
+    NATIVE_HEADER_OUTPUT,
+
+    /**
+     * Location to search for the source code of modules.
+     */
+    MODULE_SOURCE_PATH,
+
+    /**
+     * Location to search for upgradeable system modules.
+     */
+    UPGRADE_MODULE_PATH,
+
+    /**
+     * Location to search for system modules.
+     */
+    SYSTEM_MODULE_PATH,
+
+    /**
+     * Location to search for precompiled user modules.
+     */
+    MODULE_PATH;
 
     /**
      * Returns a location object with the given name.  The following
@@ -90,8 +110,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 +123,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:
--- a/src/java.compiler/share/classes/javax/tools/ToolProvider.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/java.compiler/share/classes/javax/tools/ToolProvider.java	Thu Apr 02 18:57:23 2015 -0700
@@ -27,6 +27,7 @@
 
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -151,8 +152,12 @@
     private <T> T getSystemTool(Class<T> clazz, String name) {
         Class<? extends T> c = getSystemToolClass(clazz, name);
         try {
-            return c.asSubclass(clazz).newInstance();
-        } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) {
+            Constructor<? extends T> con = c.getConstructor();
+            /* temporary workaround; awaiting tools providing qualified exports to java.compiler */
+            con.setAccessible(true);
+            /* end workaround */
+            return con.newInstance();
+        } catch (ReflectiveOperationException | RuntimeException | Error e) {
             return trace(WARNING, e);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.compiler/share/classes/module-info.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+module java.compiler {
+    requires java.logging;
+
+    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;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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 { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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
+ * 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;
+
+/**
+ *
+ */
+public interface ExportsTree extends DirectiveTree {
+    ExpressionTree getExportName();
+    List<? extends ExpressionTree> getModuleNames();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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
+ * 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;
+
+
+/**
+ *
+ */
+public interface ModuleTree extends Tree {
+    ExpressionTree getName();
+    List<? extends DirectiveTree> getDirectives();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,34 @@
+/*
+ * 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
+ * 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;
+
+/*
+ *
+ */
+public interface ProvidesTree extends DirectiveTree {
+    ExpressionTree getServiceName();
+    ExpressionTree getImplementationName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,31 @@
+/*
+ * 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
+ * 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;
+
+public interface RequiresTree extends DirectiveTree {
+    boolean isPublic();
+    ExpressionTree getModuleName();
+}
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -606,6 +606,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.
          */
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -482,6 +482,12 @@
      */
     R visitWildcard(WildcardTree node, P p);
 
+    R visitModule(ModuleTree node, P p);
+    R visitExports(ExportsTree node, P p);
+    R visitProvides(ProvidesTree node, P p);
+    R visitRequires(RequiresTree node, P p);
+    R visitUses(UsesTree node, P p);
+
     /**
      * Visits an unknown type of Tree node.
      * This can occur if the language evolves and new kinds
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,31 @@
+
+/*
+ * 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
+ * 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;
+
+public interface UsesTree extends DirectiveTree {
+    ExpressionTree getServiceName();
+}
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -720,14 +720,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);
     }
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -847,6 +847,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}.
      *
--- a/src/jdk.compiler/share/classes/com/sun/tools/classfile/AccessFlags.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/AccessFlags.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/classfile/Attribute.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/Attribute.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -47,11 +47,14 @@
     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 +68,7 @@
     public static final String StackMap                 = "StackMap";
     public static final String StackMapTable            = "StackMapTable";
     public static final String Synthetic                = "Synthetic";
+    public static final String Version                  = "Version";
 
     public static class Factory {
         public Factory() {
@@ -105,7 +109,7 @@
         protected void init() {
             standardAttributes = new HashMap<>();
             standardAttributes.put(AnnotationDefault, AnnotationDefault_attribute.class);
-            standardAttributes.put(BootstrapMethods,  BootstrapMethods_attribute.class);
+            standardAttributes.put(BootstrapMethods, BootstrapMethods_attribute.class);
             standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class);
             standardAttributes.put(Code,              Code_attribute.class);
             standardAttributes.put(CompilationID,     CompilationID_attribute.class);
@@ -113,24 +117,28 @@
             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(MethodParameters,  MethodParameters_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);
             standardAttributes.put(RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations_attribute.class);
             standardAttributes.put(RuntimeVisibleTypeAnnotations, RuntimeVisibleTypeAnnotations_attribute.class);
             standardAttributes.put(RuntimeInvisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations_attribute.class);
-            standardAttributes.put(Signature,         Signature_attribute.class);
+            standardAttributes.put(Signature,     Signature_attribute.class);
             standardAttributes.put(SourceDebugExtension, SourceDebugExtension_attribute.class);
             standardAttributes.put(SourceFile,        SourceFile_attribute.class);
             standardAttributes.put(SourceID,          SourceID_attribute.class);
             standardAttributes.put(StackMap,          StackMap_attribute.class);
             standardAttributes.put(StackMapTable,     StackMapTable_attribute.class);
             standardAttributes.put(Synthetic,         Synthetic_attribute.class);
+            standardAttributes.put(Version,           Version_attribute.class);
         }
 
         private Map<String,Class<? extends Attribute>> standardAttributes;
@@ -170,11 +178,14 @@
         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 +199,6 @@
         R visitStackMap(StackMap_attribute attr, P p);
         R visitStackMapTable(StackMapTable_attribute attr, P p);
         R visitSynthetic(Synthetic_attribute attr, P p);
+        R visitVersion(Version_attribute attr, P p);
     }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/classfile/ClassWriter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/ClassWriter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -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,31 @@
             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 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 +444,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 +452,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 +470,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 +483,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 +499,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 +515,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 +525,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 +588,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 +596,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 +631,7 @@
             return null;
         }
 
+        @Override
         public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
             if (stackMapWriter == null)
                 stackMapWriter = new StackMapTableWriter();
@@ -559,6 +642,7 @@
             return null;
         }
 
+        @Override
         public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
             return null;
         }
@@ -567,6 +651,12 @@
             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 +671,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 +709,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 +789,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)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/Hashes_attribute.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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
+ * 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.Version), 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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/MainClass_attribute.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,64 @@
+/*
+ * 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
+ * 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/Module_attribute.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,160 @@
+/*
+ * 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
+ * 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(int index, 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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/classfile/Version_attribute.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * 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;
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -37,6 +37,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;
@@ -348,6 +349,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);
@@ -382,6 +427,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);
@@ -393,6 +449,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);
@@ -415,9 +482,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) {
@@ -435,6 +513,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 {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -36,18 +36,18 @@
 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.*;
 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;
 import com.sun.tools.javac.file.JRTIndex;
 import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
 import com.sun.tools.javac.jvm.ClassReader;
 import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.javac.util.*;
@@ -58,6 +58,7 @@
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 
 import static com.sun.tools.javac.main.Option.*;
+
 import com.sun.tools.javac.util.Dependencies.CompletionCause;
 
 /**
@@ -172,7 +173,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);
@@ -326,7 +327,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");
         }
@@ -340,7 +341,7 @@
                 }
                 currentClassFile = classfile;
                 if (verbose) {
-                    log.printVerbose("loading", currentClassFile.toString());
+                    log.printVerbose("loading", currentClassFile.getName());
                 }
                 if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
                     reader.readClassFile(c);
@@ -418,6 +419,9 @@
      *             is older.
      */
     protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
+        if (p.modle == null && p.modleHint != null)
+            p.modle = p.modleHint;
+
         if ((p.flags_field & EXISTS) == 0)
             for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
                 q.flags_field |= EXISTS;
@@ -435,7 +439,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) {
@@ -476,6 +480,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);
     }
@@ -499,18 +504,82 @@
         if (p.members_field == null)
             p.members_field = WriteableScope.create(p);
 
-        preferCurrent = false;
-        if (userPathsFirst) {
-            scanUserPaths(p);
-            preferCurrent = true;
-            scanPlatformPath(p);
+        ModuleSymbol msym = (p.modle != null) ? p.modle : p.modleHint;
+        if (msym != null) { // TODO: This needs to become an assert
+            // new code
+            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);
+            } else {
+                scanModulePaths(p, msym);
+            }
+            return;
+        }
+
+        // old code, to go away
+        if (p.modle != null && p.modle.classLocation != null) {
+            scanModulePaths(p, p.modle);
         } else {
-            scanPlatformPath(p);
-            scanUserPaths(p);
+            preferCurrent = false;
+            if (userPathsFirst) {
+                scanUserPaths(p);
+                preferCurrent = true;
+                scanPlatformPath(p);
+            } else {
+                scanPlatformPath(p);
+                scanUserPaths(p);
+            }
         }
         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();
+
+        Location classLocn = msym.classLocation;
+        Location sourceLocn = msym.sourceLocation;
+
+        String packageName = p.fullname.toString();
+        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));
+        }
+    }
+
     /**
      * Scans class path and source path for files in given package.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,308 @@
+/*
+ * 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.EnumSet;
+import java.util.Set;
+
+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.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+
+/**
+ *  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 {
+    public enum Kind {
+        EXPORTS,
+        PROVIDES,
+        REQUIRES,
+        USES
+    }
+
+    /** Flags for RequiresDirective. */
+    public enum RequiresFlag {
+        PUBLIC(0x0020),
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000);
+
+        // 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;
+    }
+
+    public abstract Kind getKind();
+
+    abstract <R, P> R accept(Visitor<R, P> visitor, P data);
+
+    /**
+     * 'exports' Package ';'
+     */
+    public static class ExportsDirective extends Directive {
+        public final PackageSymbol packge;
+        public final List<ModuleSymbol> modules;
+
+        public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
+            this.packge = packge;
+            this.modules = modules;
+        }
+
+        @Override
+        public Kind getKind() {
+            return Kind.EXPORTS;
+        }
+
+        @Override
+        public String toString() {
+            if (modules == null)
+                return "Exports[" + packge + "]";
+            else
+                return "Exports[" + packge + ":" + modules + "]";
+        }
+
+        @Override
+        public <R, P> R accept(Visitor<R, P> visitor, P data) {
+            return visitor.visitExports(this, data);
+        }
+    }
+
+    /**
+     * 'provides' ServiceName 'with' QualifiedIdentifer ';'
+     */
+    public static class ProvidesDirective extends Directive {
+        public final ClassSymbol service;
+        public final ClassSymbol impl;
+
+        public ProvidesDirective(ClassSymbol service, ClassSymbol impl) {
+            this.service = service;
+            this.impl = impl;
+        }
+
+        @Override
+        public Kind getKind() {
+            return Kind.PROVIDES;
+        }
+
+        @Override
+        public String toString() {
+            return "Provides[" + service + "," + impl + "]";
+        }
+
+        @Override
+        public <R, P> R accept(Visitor<R, P> visitor, P data) {
+            return visitor.visitProvides(this, data);
+        }
+    }
+
+    /**
+     * 'requires' ['public'] ModuleName ';'
+     */
+    public static class RequiresDirective extends Directive {
+        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
+        public Kind getKind() {
+            return Kind.REQUIRES;
+        }
+
+        @Override
+        public String toString() {
+            return "Requires[" + flags + "," + module + "]";
+        }
+
+        @Override
+        public <R, P> R accept(Visitor<R, P> visitor, P data) {
+            return visitor.visitRequires(this, data);
+        }
+    }
+
+    /**
+     * 'uses' ServiceName ';'
+     */
+    public static class UsesDirective extends Directive {
+        public final ClassSymbol service;
+
+        public UsesDirective(ClassSymbol service) {
+            this.service = service;
+        }
+
+        @Override
+        public Kind getKind() {
+            return Kind.USES;
+        }
+
+        @Override
+        public String toString() {
+            return "Uses[" + service + "]";
+        }
+
+        @Override
+        public <R, P> R accept(Visitor<R, P> visitor, P data) {
+            return visitor.visitUses(this, data);
+        }
+    }
+
+    public static interface Visitor<R, P> {
+        R visitRequires(RequiresDirective d, P p);
+        R visitExports(ExportsDirective d, P p);
+        R visitProvides(ProvidesDirective d, P p);
+        R visitUses(UsesDirective d, P p);
+    }
+
+    public static class SimpleVisitor<R, P> implements Visitor<R, P> {
+        protected final R DEFAULT_VALUE;
+
+        protected SimpleVisitor() {
+            DEFAULT_VALUE = null;
+        }
+
+        protected SimpleVisitor(R defaultValue) {
+            DEFAULT_VALUE = defaultValue;
+        }
+
+        protected R defaultAction(Directive d, P p) {
+            return DEFAULT_VALUE;
+        }
+
+        public final R visit(Directive d, P p) {
+            return (d == null) ? null : d.accept(this, p);
+        }
+
+        public final R visit(Iterable<? extends Directive> ds, P p) {
+            R r = null;
+            if (ds != null)
+                for (Directive d : ds)
+                    r = visit(d, p);
+            return r;
+        }
+
+        @Override
+        public R visitExports(ExportsDirective d, P p) {
+            return defaultAction(d, p);
+        }
+
+        @Override
+        public R visitProvides(ProvidesDirective d, P p) {
+            return defaultAction(d, p);
+        }
+
+        @Override
+        public R visitRequires(RequiresDirective d, P p) {
+            return defaultAction(d, p);
+        }
+
+        @Override
+        public R visitUses(UsesDirective d, P p) {
+            return defaultAction(d, p);
+        }
+    }
+
+    public static class Scanner<R, P> implements Visitor<R, P> {
+
+
+        /** Scan a single node.
+         */
+        public R scan(Directive d, P p) {
+            return (d == null) ? null : d.accept(this, p);
+        }
+
+        private R scanAndReduce(Directive d, P p, R r) {
+            return reduce(scan(d, p), r);
+        }
+
+        /** Scan a list of nodes.
+         */
+        public R scan(Iterable<? extends Directive> ds, P p) {
+            R r = null;
+            if (ds != null) {
+                boolean first = true;
+                for (Directive d : ds) {
+                    r = (first ? scan(d, p) : scanAndReduce(d, p, r));
+                    first = false;
+                }
+            }
+            return r;
+        }
+
+        /**
+         * Reduces two results into a combined result.
+         * The default implementation is to return the first parameter.
+         * The general contract of the method is that it may take any action whatsoever.
+         */
+        public R reduce(R r1, R r2) {
+            return r1;
+        }
+
+        @Override
+        public R visitExports(ExportsDirective d, P p) {
+            return null;
+        }
+
+        @Override
+        public R visitProvides(ProvidesDirective d, P p) {
+            return null;
+        }
+
+        @Override
+        public R visitRequires(RequiresDirective d, P p) {
+            return null;
+        }
+
+        @Override
+        public R visitUses(UsesDirective d, P p) {
+            return null;
+        }
+
+    }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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).
@@ -282,6 +283,12 @@
      */
     public static final long TYPE_TRANSLATED = 1L<<50;
 
+    /**
+     * Flag to indicate class symbol is for module-info
+     */
+    // TODO: do we need this; can we not infer it from the class name?
+    public static final long MODULE = 1L<<51;
+
     /** Modifier masks.
      */
     public static final int
@@ -392,7 +399,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;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,315 @@
+/*
+ * 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.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.Scope.WriteableScope;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+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_MODULE_PATH,
+                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);
+                        }
+                    } 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() {
+        Location sp = fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+                ? StandardLocation.SOURCE_PATH
+                : StandardLocation.CLASS_PATH;
+        Location cp = StandardLocation.CLASS_PATH;
+
+        try {
+            JavaFileObject src_fo = fileManager.getJavaFileForInput(sp,
+                    names.module_info.toString(), Kind.SOURCE);
+            JavaFileObject class_fo = fileManager.getJavaFileForInput(cp,
+                    names.module_info.toString(), 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;
+                // TODO: defer with completer?
+                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.sourceLocation = StandardLocation.SOURCE_PATH;
+            msym.classLocation = StandardLocation.CLASS_PATH;
+            return msym;
+
+        } catch (IOException e) {
+            throw new Error(e); // FIXME
+        }
+    }
+
+    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 (toFind == msym || toFind == null) {
+                            // Note: cannot return msym directly, because we must finish
+                            // processing this set first
+                            results.add(msym);
+                        }
+                    } else {
+                        log.error("duplicate.module.on.path",
+                                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) {
+                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;
+        }
+    }
+
+    JCDiagnostic getDescription(StandardLocation l) {
+        return diags.fragment("locn." + StringUtils.toLowerCase(l.getName()));
+    }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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")
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -27,12 +27,16 @@
 
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Inherited;
+import java.util.EnumMap;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
 import javax.lang.model.element.*;
+import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.comp.Attr;
@@ -43,6 +47,8 @@
 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.Directive.*;
 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.*;
@@ -824,6 +830,67 @@
             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<Directive> directives;
+        public List<RequiresDirective> requires;
+        public List<ExportsDirective> exports;
+        public List<ProvidesDirective> provides;
+        public List<UsesDirective> uses;
+
+        public ClassSymbol module_info;
+
+        public Set<PackageSymbol> visiblePackages;
+
+        /**
+         * 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.modle = 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
+        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) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+    }
 
     /** A class for package symbols
      */
@@ -833,6 +900,8 @@
         public WriteableScope members_field;
         public Name fullname;
         public ClassSymbol package_info; // see bug 6443073
+        public ModuleSymbol modle;
+        public ModuleSymbol modleHint;
 
         public PackageSymbol(Name name, Type type, Symbol owner) {
             super(PCK, 0, name, type, owner);
@@ -923,6 +992,12 @@
     /** A class for class symbols
      */
     public static class ClassSymbol extends TypeSymbol implements TypeElement {
+        /**
+         * The module for the class.
+         */
+        // TODO: is this required? the value can be obtained from the enclosing package
+        // Only read access is currently for module-info.class in ClassWriter
+        public ModuleSymbol modle;
 
         /** a scope for all class members; variables, methods and inner classes
          *  type parameters are not part of this scope
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -26,20 +26,18 @@
 package com.sun.tools.javac.code;
 
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Set;
 
 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.OperatorSymbol;
+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;
@@ -50,8 +48,7 @@
 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.ByteCodes;
-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;
@@ -62,10 +59,10 @@
 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.*;
-import static com.sun.tools.javac.jvm.ByteCodes.*;
 import static com.sun.tools.javac.code.TypeTag.*;
 
 /** A class that defines all predefined constants and operators
@@ -106,7 +103,19 @@
 
     private final Names names;
     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.
      */
@@ -144,6 +153,10 @@
     /** The builtin type of all methods. */
     public final ClassSymbol methodClass;
 
+    /** A symbol for the java.base module.
+     */
+    public final ModuleSymbol javaBase;
+
     /** Predefined types.
      */
     public final Type objectType;
@@ -212,7 +225,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()];
 
@@ -229,6 +242,10 @@
      */
     public final Map<Name, PackageSymbol> packages = new HashMap<>();
 
+    /** A hashtable giving the encountered modules.
+     */
+    public final Map<Name, ModuleSymbol> modules = new LinkedHashMap<>();
+
     public void initType(Type type, ClassSymbol c) {
         type.tsym = c;
         typeOfTag[type.getTag().ordinal()] = type;
@@ -243,7 +260,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.
@@ -254,13 +271,14 @@
      *  @param s The name of the class.
      */
     private Type enterClass(String s) {
-        return enterClass(names.fromString(s)).type;
+        return enterClass(javaBase, names.fromString(s)).type;
     }
 
     public void synthesizeEmptyInterfaceIfMissing(final Type type) {
         final Completer completer = type.tsym.completer;
         if (completer != null) {
             type.tsym.completer = new Completer() {
+                @Override
                 public void complete(Symbol sym) throws CompletionFailure {
                     try {
                         completer.complete(sym);
@@ -274,10 +292,11 @@
     }
 
     public void synthesizeBoxTypeIfMissing(final Type type) {
-        ClassSymbol sym = enterClass(boxedName[type.getTag().ordinal()]);
+        ClassSymbol sym = enterClass(javaBase, boxedName[type.getTag().ordinal()]);
         final Completer completer = sym.completer;
         if (completer != null) {
             sym.completer = new Completer() {
+                @Override
                 public void complete(Symbol sym) throws CompletionFailure {
                     try {
                         completer.complete(sym);
@@ -327,22 +346,31 @@
         context.put(symtabKey, this);
 
         names = Names.instance(context);
-        target = Target.instance(context);
 
         // Create the unknown type
         unknownType = new UnknownType();
 
+        final JavacMessages messages = JavacMessages.instance(context);
+
         // create the basic builtin symbols
+        unnamedModule = new ModuleSymbol(names.empty, null) {
+                @Override
+                public String toString() {
+                    return messages.getLocalizedString("compiler.misc.unnamed.module");
+                }
+            };
+        errModule = new ModuleSymbol(names.empty, null) { };
+        noModule = new ModuleSymbol(names.empty, null) { };
         rootPackage = new PackageSymbol(names.empty, null);
         packages.put(names.empty, rootPackage);
-        final JavacMessages messages = JavacMessages.instance(context);
         unnamedPackage = new PackageSymbol(names.empty, rootPackage) {
+                @Override
                 public String toString() {
                     return messages.getLocalizedString("compiler.misc.unnamed.package");
                 }
             };
         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);
             }
@@ -391,6 +419,9 @@
         rootPackage.completer = initialCompleter;
         unnamedPackage.completer = initialCompleter;
 
+        // Get the initial completer for ModuleSymbols from Modules
+        moduleCompleter = Modules.instance(context).getCompleter();
+
         // Enter symbols for basic types.
         scope.enter(byteType.tsym);
         scope.enter(shortType.tsym);
@@ -407,7 +438,14 @@
 
         classes.put(predefClass.fullname, predefClass);
 
-        // Enter predefined classes.
+        Source source = Source.instance(context);
+        Options options = Options.instance(context);
+        boolean noModules = options.isSet("noModules");
+        javaBase = source.allowModules() && !noModules
+                ? enterModule(names.java_base)
+                : noModule;
+
+        // 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");
@@ -433,7 +471,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(javaBase, names.java_lang_Enum);
         enumFinalFinalize =
             new MethodSymbol(PROTECTED|FINAL|HYPOTHETICAL,
                              names.finalize,
@@ -525,6 +563,10 @@
      *  and owner and enter in `classes' unless already there.
      */
     public ClassSymbol enterClass(Name name, TypeSymbol owner) {
+        return enterClass(null, name, owner);
+    }
+
+    public ClassSymbol enterClass(ModuleSymbol msym, Name name, TypeSymbol owner) {
         Name flatname = TypeSymbol.formFlatName(name, owner);
         ClassSymbol c = classes.get(flatname);
         if (c == null) {
@@ -551,7 +593,11 @@
      * @return a newly created class symbol
      * @throws AssertionError if the class symbol already exists
      */
-    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
+//    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
+//        return enterClass(null, flatName, classFile);
+//    }
+
+    public ClassSymbol enterClass(ModuleSymbol msym, 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",
@@ -564,7 +610,9 @@
         Name packageName = Convert.packagePart(flatName);
         PackageSymbol owner = packageName.isEmpty()
                                 ? unnamedPackage
-                                : enterPackage(packageName);
+                                : enterPackage(msym, packageName);
+        if (owner != unnamedPackage && owner.modle == null && msym != null)
+            owner.modle = msym;
         cs = defineClass(Convert.shortName(flatName), owner);
         cs.classfile = classFile;
         classes.put(flatName, cs);
@@ -575,37 +623,66 @@
      *  and enter in `classes' unless already there.
      */
     public ClassSymbol enterClass(Name flatname) {
+        return enterClass(null, flatname);
+    }
+
+    public ClassSymbol enterClass(ModuleSymbol msym, Name flatname) {
         ClassSymbol c = classes.get(flatname);
         if (c == null)
-            return enterClass(flatname, (JavaFileObject)null);
+            return enterClass(msym, flatname, (JavaFileObject)null);
         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) {
+        return enterPackage(null, fullname).exists();
     }
 
     /** Make a package, given its fully qualified name.
      */
-    public PackageSymbol enterPackage(Name fullname) {
+    public PackageSymbol enterPackage(ModuleSymbol currModule, Name fullname) {
         PackageSymbol p = packages.get(fullname);
         if (p == null) {
             Assert.check(!fullname.isEmpty(), "rootPackage missing!");
             p = new PackageSymbol(
-                Convert.shortName(fullname),
-                enterPackage(Convert.packagePart(fullname)));
+                    Convert.shortName(fullname),
+                    enterPackage(null, Convert.packagePart(fullname)));
             p.completer = initialCompleter;
             packages.put(fullname, p);
         }
+        if (p.modle == null && currModule != null) {
+            p.modleHint = currModule;
+            if (p.completer == null)
+                p.completer = initialCompleter;
+        }
         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));
+    // temporary, for compatibility
+    public PackageSymbol enterPackage(Name fullname) {
+        return enterPackage(null, fullname);
     }
+
+    public ModuleSymbol enterModule(Name name) {
+        ModuleSymbol msym = modules.get(name);
+        if (msym == null) {
+            msym = ModuleSymbol.create(name, names.module_info);
+            msym.completer = moduleCompleter;
+            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;
+        ClassSymbol info = msym.module_info;
+        info.fullname = msym.name.append('.', names.module_info);
+        info.flatname = info.fullname;
+        modules.put(name, msym);
+    }
+
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -1406,7 +1406,7 @@
 
     public static class PackageType extends Type implements NoType {
 
-        PackageType(TypeSymbol tsym) {
+        PackageType(PackageSymbol tsym) {
             // Package types cannot be annotated
             super(tsym, TypeMetadata.empty);
         }
@@ -1442,6 +1442,50 @@
         }
     }
 
+    public static class ModuleType extends Type implements NoType {
+
+        ModuleType(ModuleSymbol tsym) {
+            // Module types cannot be annotated
+            super(tsym, TypeMetadata.empty);
+        }
+
+        @Override
+        public ModuleType clone(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() {
+            throw new UnsupportedOperationException();
+//            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.
@@ -2189,6 +2233,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);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Thu Apr 02 18:57:23 2015 -0700
@@ -47,6 +47,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.comp.Annotate;
 import com.sun.tools.javac.comp.Annotate.Worker;
 import com.sun.tools.javac.comp.Attr;
@@ -621,6 +622,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);
                 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Thu Apr 02 18:57:23 2015 -0700
@@ -3977,7 +3977,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.javaBase, syms.boxedName[t.getTag().ordinal()]);
     }
 
     /**
@@ -3996,7 +3996,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.javaBase, box)) != null)
                 return syms.typeOfTag[i];
         }
         return Type.noType;
@@ -4576,6 +4576,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); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
@@ -4147,13 +4149,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);
+        }
     }
 
     /**
@@ -4169,6 +4177,22 @@
         }
     }
 
+    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);
+//        System.err.println("Attr.attribModule: " + env + " " + env.tree);
+        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
@@ -4267,6 +4291,57 @@
         // nothing to do
     }
 
+    public void visitModuleDef(JCModuleDecl tree) {
+        ModuleSymbol msym = env.toplevel.modle;
+        msym.directives = List.nil();
+        msym.provides = List.nil();
+        msym.uses = List.nil();
+        attribStats(tree.directives, env);
+        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);
+    }
+
+    public void visitExports(JCExports tree) {
+        ModuleSymbol msym = env.toplevel.modle;
+        msym.directives = msym.directives.prepend(tree.directive);
+    }
+
+    public void visitProvides(JCProvides tree) {
+        ModuleSymbol msym = env.toplevel.modle;
+
+//        syms.enterPackage(msym, Convert.packagePart(TreeInfo.fullName(tree.implName))).complete();
+
+        Type st = attribType(tree.serviceName, env, syms.objectType);
+        Type it = attribType(tree.implName, env, st);
+        if (st.hasTag(CLASS) && it.hasTag(CLASS)) {
+            ClassSymbol service = (ClassSymbol) st.tsym;
+            ClassSymbol impl = (ClassSymbol) it.tsym;
+            Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impl);
+            msym.provides = msym.provides.prepend(d);
+            msym.directives = msym.directives.prepend(d);
+        }
+    }
+
+    public void visitRequires(JCRequires tree) {
+        ModuleSymbol msym = env.toplevel.modle;
+        msym.directives = msym.directives.prepend(tree.directive);
+    }
+
+    public void visitUses(JCUses tree) {
+        ModuleSymbol msym = env.toplevel.modle;
+        Type st = attribType(tree.qualid, env, syms.objectType);
+        if (st.hasTag(CLASS)) {
+            ClassSymbol service = (ClassSymbol) st.tsym;
+            Directive.UsesDirective d = new Directive.UsesDirective(service);
+            msym.uses = msym.uses.prepend(d);
+            msym.directives = msym.directives.prepend(d);
+        }
+    }
+
     /** Finish the attribution of a class. */
     private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
         JCClassDecl tree = (JCClassDecl)env.tree;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -25,7 +25,6 @@
 
 package com.sun.tools.javac.comp;
 
-import java.util.*;
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileManager;
 
@@ -34,7 +33,6 @@
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.main.Option.PkgInfo;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
@@ -42,7 +40,6 @@
 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.*;
 
@@ -99,6 +96,8 @@
     JavaFileManager fileManager;
     PkgInfo pkginfoOpt;
     TypeEnvs typeEnvs;
+    Modules modules;
+    JCDiagnostic.Factory diags;
 
     private final Todo todo;
 
@@ -121,6 +120,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),
@@ -231,6 +232,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 tree.sym != null;
+        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 +295,72 @@
 
     @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);
+        } else {
+            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 = syms.unnamedPackage;
             }
-        } 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);
+            // TODO: add proper checks
+            // should always be safe to install tree.modle if compatible
+            if (tree.modle != null && tree.modle.name != null)
+                tree.packge.modle = tree.modle;
+
+            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(name, tree.packge);
+                c.flatname = names.fromString(tree.packge + "." + name);
+                c.sourcefile = tree.sourcefile;
+                c.completer = null;
+                c.members_field = WriteableScope.create(c);
+                tree.packge.package_info = c;
             }
-            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(name, tree.packge);
-            c.flatname = names.fromString(tree.packge + "." + name);
-            c.sourcefile = tree.sourcefile;
-            c.completer = null;
-            c.members_field = WriteableScope.create(c);
-            tree.packge.package_info = c;
-        }
-        classEnter(tree.defs, topEnv);
-        if (addEnv) {
-            todo.append(packageEnv);
+            classEnter(tree.defs, topEnv);
+            if (addEnv) {
+                todo.append(packageEnv);
+            }
         }
         log.useSource(prev);
         result = null;
@@ -390,6 +424,7 @@
         c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
         c.sourcefile = env.toplevel.sourcefile;
         c.members_field = WriteableScope.create(c);
+        c.modle = env.toplevel.modle;
 
         ClassType ct = (ClassType)c.type;
         if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
@@ -421,6 +456,8 @@
         // Recursively enter all member classes.
         classEnter(tree.defs, localEnv);
 
+//        Assert.checkNonNull(c.modle, c.sourcefile.toString());
+
         result = c.type;
     }
     //where
@@ -453,6 +490,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
@@ -474,6 +518,18 @@
      *  @param c          The class symbol to be processed or null to process all.
      */
     public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
+        // 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(trees, c)) {
+            if (c != null)
+                throw new CompletionFailure(c, diags.fragment("cant.resolve.modules"));
+            return;
+        }
+
         annotate.enterStart();
         ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
         if (typeEnter.completionEnabled) uncompleted = new ListBuffer<>();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
      *************************************************************************/
@@ -2414,6 +2422,10 @@
             tree.underlyingType.accept(this);
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -2603,6 +2615,10 @@
             super.visitTry(tree);
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Apr 02 18:57:23 2015 -0700
@@ -2341,25 +2341,19 @@
 
     public void visitPackageDef(JCPackageDecl tree) {
         if (!needPackageInfoClass(tree))
-            return;
-
-        Name name = names.package_info;
+                        return;
+
         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.setAttributes(tree.packge);
+        c.modle = attrEnv.toplevel.modle;
         c.flags_field |= flags;
-        c.setAttributes(tree.packge);
         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) {
@@ -2380,6 +2374,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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,605 @@
+/*
+ * 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.comp;
+
+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;
+import java.util.Map;
+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.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.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.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Symtab;
+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.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.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.UNATTRIBUTED;
+import static com.sun.tools.javac.code.Kinds.Kind.MDL;
+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 final Log log;
+    private final Names names;
+    private final Symtab syms;
+    private final JavaFileManager fileManager;
+    private final ModuleFinder moduleFinder;
+    private final boolean multiModuleMode;
+    private final boolean allowModules;
+
+    private final boolean noModules;
+
+    ModuleSymbol defaultModule;
+
+    private final String addModuleExportsOpt;
+    private Map<ModuleSymbol, Set<ExportsDirective>> addModuleExports;
+
+    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);
+        moduleFinder = ModuleFinder.instance(context);
+        fileManager = context.get(JavaFileManager.class);
+        allowModules = Source.instance(context).allowModules();
+        Options options = Options.instance(context);
+
+        // 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;
+
+        addModuleExportsOpt = options.get(Option.XXADDMODULEEXPORTS);
+    }
+
+    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;
+            }
+            return true;
+        }
+
+        int startErrors = log.nerrors;
+
+        depth++;
+        try {
+            // scan trees for module defs
+            Set<ModuleSymbol> rootModules = enterModules(trees, c);
+
+            setCompilationUnitModules(trees, rootModules);
+
+            for (ModuleSymbol msym: rootModules) {
+                msym.complete();
+            }
+
+            return (log.nerrors == startErrors);
+        } finally {
+            depth--;
+        }
+    }
+
+    public Completer getCompleter() {
+        return mainCompleter;
+    }
+
+
+    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) {
+                   syms.enterModule(sym, name);
+               } else {
+                   // TODO: validate name
+               }
+            } else {
+                sym = syms.enterModule(name);
+                if (sym.module_info.sourcefile != null) {
+                    log.error(decl.pos(), "duplicate.module", name);
+                    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(), "too.many.modules");
+            }
+
+        } else if (isModuleInfo) {
+            if (multiModuleMode) {
+                JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head;
+                log.error(tree.pos(), "expected.module");
+            }
+        } else if (isModuleDecl) {
+            JCTree tree = toplevel.defs.head;
+            log.error(tree.pos(), "module.decl.sb.in.module-info.java");
+        }
+    }
+
+    private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules) {
+        // update the module for each compilation unit
+        if (multiModuleMode) {
+            for (JCCompilationUnit tree: trees) {
+                if (tree.defs.isEmpty())
+                    continue;
+
+                JavaFileObject prev = log.useSource(tree.sourcefile);
+                try {
+                    Location locn = getModuleLocation(tree);
+                    if (locn != null) {
+                        Name name = names.fromString(fileManager.inferModuleName(locn));
+                        ModuleSymbol 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(), "cant.determine.module");
+                        tree.modle = syms.errModule;
+                    }
+                } catch (IOException e) {
+                    throw new Error(e); // FIXME
+                } finally {
+                    log.useSource(prev);
+                }
+            }
+        } else {
+            if (defaultModule == null) {
+                switch (rootModules.size()) {
+                    case 0:
+                        defaultModule = moduleFinder.findSingleModule();
+                        if (defaultModule == syms.unnamedModule) {
+                            // Question: why not do findAllModules and initVisiblePackages here?
+                            // i.e. body of unnamedModuleCompleter
+                            defaultModule.completer = getUnnamedModuleCompleter();
+                        } else {
+                            // 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:
+                        defaultModule = rootModules.iterator().next();
+                        break;
+                    default:
+                        Assert.error("too many modules");
+                }
+                defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                defaultModule.classLocation = StandardLocation.CLASS_PATH;
+            } else {
+                Assert.check(rootModules.isEmpty());
+            }
+
+            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 final Completer mainCompleter = new Completer() {
+        @Override
+        public void complete(Symbol sym) throws CompletionFailure {
+            ModuleSymbol msym = (ModuleSymbol) sym;
+            moduleFinder.findModule(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.getKind() == Kind.CLASS) {
+                completeModule(msym);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "mainCompleter";
+        }
+    };
+
+    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);
+                } 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<>();
+
+        private <T extends JCTree> void acceptAll(List<T> trees) {
+            for (List<T> l = trees; l.nonEmpty(); l = l.tail)
+                l.head.accept(this);
+        }
+
+        @Override
+        public void visitModuleDef(JCModuleDecl tree) {
+            sym = Assert.checkNonNull(tree.sym);
+            allRequires.clear();
+            allExports.clear();
+
+            sym.requires = List.nil();
+            sym.exports = List.nil();
+            acceptAll(tree.directives);
+            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(), "module.not.found", msym);
+            } else if ((msym.flags_field & UNATTRIBUTED) != 0) {
+                log.error(tree.moduleName.pos(), "cyclic.requires", msym);
+            } else if (allRequires.contains(msym)) {
+                log.error(tree.moduleName.pos(), "duplicate.requires", 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(name);
+            if (!allExports.add(packge)) {
+                log.error(tree.qualid.pos(), "duplicate.exports", 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(), "module.not.found", msym);
+                    } else if (!to.add(msym)) {
+                        log.error(n.pos(), "duplicate.exports", 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);
+            return moduleFinder.findModule(name);
+            } catch (Throwable t) {
+                System.err.println("Module " + sym + "; lookup export " + moduleName);
+                throw t;
+            }
+        }
+    }
+
+    private Completer getUnnamedModuleCompleter() {
+        List<ModuleSymbol> allModules = moduleFinder.findAllModules();
+        return new Symbol.Completer() {
+            @Override
+            public void complete(Symbol sym) throws CompletionFailure {
+                ModuleSymbol msym = (ModuleSymbol) sym;
+                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);
+        Set<ModuleSymbol> readable = new HashSet<>();
+        Set<ModuleSymbol> requiresPublic = new HashSet<>();
+        for (RequiresDirective d: msym.requires) {
+            d.module.complete();
+            readable.add(d.module);
+            Set<ModuleSymbol> s = requiresPublicCache.get(d.module);
+            if (s == null) {
+                System.err.println("no entry in cache for " + d.module);
+            }
+            readable.addAll(s);
+            if (d.flags.contains(RequiresFlag.PUBLIC)) {
+                requiresPublic.add(d.module);
+                requiresPublic.addAll(s);
+            }
+        }
+        requiresPublicCache.put(msym, requiresPublic);
+        initVisiblePackages(msym, readable);
+        for (ExportsDirective d: msym.exports) {
+            d.packge.modle = msym;
+        }
+
+    }
+
+    private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) {
+        initAddModuleExports();
+
+        msym.visiblePackages = new LinkedHashSet<>();
+        msym.visiblePackages.add(syms.rootPackage);
+
+        for (ModuleSymbol rm : readable) {
+            addVisiblePackages(msym, rm.exports);
+            Set<ExportsDirective> extra = addModuleExports.get(rm);
+            if (extra != null)
+                addVisiblePackages(msym, extra);
+        }
+    }
+
+    private void addVisiblePackages(ModuleSymbol msym, Collection<ExportsDirective> directives) {
+        for (ExportsDirective d: directives) {
+            if (d.modules == null || d.modules.contains(msym))
+                msym.visiblePackages.add(d.packge);
+        }
+    }
+
+    private void initAddModuleExports() {
+        if (addModuleExports != null)
+            return;
+
+        addModuleExports = new LinkedHashMap<>();
+
+        if (addModuleExportsOpt == null)
+            return;
+
+        for (String s: addModuleExportsOpt.split("[ ,]+")) {
+            if (s.isEmpty())
+                continue;
+            int slash = s.indexOf('/');
+            String moduleName = s.substring(0, slash);
+            ModuleSymbol msym = syms.enterModule(names.fromString(moduleName));
+            int equals = s.indexOf('=', slash + 1);
+            ExportsDirective d;
+            if (equals == -1) {
+                String packageName = s.substring(slash + 1);
+                PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
+                p.modle = msym;
+                d = new ExportsDirective(p, null);
+            } else {
+                String packageName = s.substring(slash + 1, equals);
+                String toModule = s.substring(equals + 1);
+                PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
+                p.modle = msym;
+                ModuleSymbol m = syms.enterModule(names.fromString(toModule));
+                d = new ExportsDirective(p, List.of(m));
+            }
+
+            Set<ExportsDirective> extra = addModuleExports.get(msym);
+            if (extra == null) {
+                addModuleExports.put(msym, extra = new LinkedHashSet<>());
+            }
+            extra.add(d);
+        }
+    }
+
+    // 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();
+    }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Apr 02 18:57:23 2015 -0700
@@ -94,11 +94,14 @@
     JCDiagnostic.Factory diags;
     public final boolean allowMethodHandles;
     public final boolean allowFunctionalInterfaceMostSpecific;
+    public final boolean allowModules;
     public final boolean checkVarargsAccessAfterResolution;
     private final boolean debugResolve;
     private final boolean compactMethodDiags;
     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
 
+    private final boolean checkModuleAccess;
+
     WriteableScope polymorphicSignatureScope;
 
     protected Resolve(Context context) {
@@ -133,6 +136,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
@@ -311,8 +320,17 @@
                     (env.enclMethod.mods.flags & ANONCONSTR) != 0;
                 break;
             default: // error recovery
+                isAccessible = true;
+                break;
             case PUBLIC:
-                isAccessible = true;
+                if (allowModules && checkModuleAccess) {
+                    ModuleSymbol currModule = env.toplevel.modle;
+                    PackageSymbol p = c.packge();
+                    isAccessible =
+                        (currModule == p.modle) || currModule.visiblePackages.contains(p);
+                } else {
+                    isAccessible = true;
+                }
                 break;
             case PROTECTED:
                 isAccessible =
@@ -2088,7 +2106,7 @@
         }
 
         if (kind.contains(KindSelector.PCK))
-            return syms.enterPackage(name);
+            return syms.enterPackage(env.toplevel.modle, name);
         else return bestSoFar;
     }
 
@@ -2104,7 +2122,7 @@
         Symbol bestSoFar = typeNotFound;
         PackageSymbol pack = null;
         if (kind.contains(KindSelector.PCK)) {
-            pack = syms.enterPackage(fullname);
+            pack = syms.enterPackage(env.toplevel.modle, fullname);
             if (pack.exists()) return pack;
         }
         if (kind.contains(KindSelector.TYP)) {
@@ -3853,9 +3871,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(),
@@ -3868,6 +3892,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();
+        }
     }
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -160,6 +160,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); });
@@ -807,7 +809,7 @@
             // name as a top-level package.
             if (checkClash &&
                 sym.owner.kind == PCK && sym.owner != syms.unnamedPackage &&
-                syms.packageExists(sym.fullname)) {
+                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 &&
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java	Thu Apr 02 18:57:23 2015 -0700
@@ -35,7 +35,6 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.ProviderNotFoundException;
-import java.nio.file.spi.FileSystemProvider;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -96,11 +95,6 @@
     private final FileSystem jrtfs;
 
     /**
-     * The set of module directories within the jrt: file system.
-     */
-    private final Set<Path> jrtModules;
-
-    /**
      * A lazily evaluated set of entries about the contents of the jrt: file system.
      */
     private final Map<RelativeDirectory, SoftReference<Entry>> entries;
@@ -184,14 +178,6 @@
      */
     private JRTIndex() throws IOException {
         jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        jrtModules = new LinkedHashSet<>();
-        Path root = jrtfs.getPath("/");
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
-            for (Path entry: stream) {
-                if (Files.isDirectory(entry))
-                    jrtModules.add(entry);
-            }
-        }
         entries = new HashMap<>();
     }
 
@@ -205,18 +191,24 @@
         if (e == null) {
             Map<String, Path> files = new LinkedHashMap<>();
             Set<RelativeDirectory> subdirs = new LinkedHashSet<>();
-            for (Path module: jrtModules) {
-                Path p = rd.getFile(module);
-                if (!Files.exists(p))
-                    continue;
-                try (DirectoryStream<Path> stream = Files.newDirectoryStream(p)) {
-                    for (Path entry: stream) {
-                        String name = entry.getFileName().toString();
-                        if (Files.isRegularFile(entry)) {
-                            // TODO: consider issue of files with same name in different modules
-                            files.put(name, entry);
-                        } else if (Files.isDirectory(entry)) {
-                            subdirs.add(new RelativeDirectory(rd, name));
+            Path pkgs = jrtfs.getPath("/packages");
+            Path pdir = pkgs.resolve(rd.getPath().replaceAll("/$", "").replace("/", "."));
+            if (Files.exists(pdir)) {
+                try (DirectoryStream<Path> modules = Files.newDirectoryStream(pdir)) {
+                    for (Path module: modules) {
+                        Path p = rd.getFile(module);
+                        if (!Files.exists(p))
+                            continue;
+                        try (DirectoryStream<Path> stream = Files.newDirectoryStream(p)) {
+                            for (Path entry: stream) {
+                                String name = entry.getFileName().toString();
+                                if (Files.isRegularFile(entry)) {
+                                    // TODO: consider issue of files with same name in different modules
+                                    files.put(name, entry);
+                                } else if (Files.isDirectory(entry)) {
+                                    subdirs.add(new RelativeDirectory(rd, name));
+                                }
+                            }
                         }
                     }
                 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Thu Apr 02 18:57:23 2015 -0700
@@ -630,7 +630,8 @@
      * Close the JavaFileManager, releasing resources.
      */
     @Override @DefinedBy(Api.COMPILER)
-    public void close() {
+    public void close() throws IOException {
+        locations.close();
         for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
             Archive a = i.next();
             i.remove();
@@ -715,7 +716,8 @@
 
     @Override @DefinedBy(Api.COMPILER)
     public boolean hasLocation(Location location) {
-        return getLocation(location) != null;
+        nullCheck(location);
+        return locations.hasLocation(location);
     }
 
     @Override @DefinedBy(Api.COMPILER)
@@ -936,6 +938,54 @@
     }
 
     @Override @DefinedBy(Api.COMPILER)
+    public Location getModuleLocation(Location location, String moduleName) {
+        nullCheck(location);
+        nullCheck(moduleName);
+        return locations.getModuleLocation(location, moduleName);
+
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        nullCheck(location);
+        if (!(fo instanceof RegularFileObject))
+            throw new IllegalArgumentException(fo.getName());
+        Path f = ((RegularFileObject) fo).file;
+        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++;
+                }
+            }
+        }
+        if (depth < f.getNameCount()) {
+            Path root = f.getRoot();
+            Path subpath = f.subpath(0, f.getNameCount() - 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 RegularFileObject) {
             return ((RegularFileObject) file).file;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Thu Apr 02 18:57:23 2015 -0700
@@ -28,11 +28,16 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
+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;
@@ -42,24 +47,30 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Objects;
+import java.util.NoSuchElementException;
 import java.util.Set;
 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;
 import javax.tools.StandardLocation;
 
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.javac.code.Lint;
 import com.sun.tools.javac.main.Option;
 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;
@@ -108,10 +119,29 @@
     // Locations can use Paths.get(URI.create("jrt:"))
     static final Path JRT_MARKER_FILE = Paths.get("JRT_MARKER_FILE");
 
+    Map<Path, FileSystem> fileSystems = new LinkedHashMap<>();
+
     public Locations() {
         initHandlers();
     }
 
+    public void close() throws IOException {
+        ListBuffer<IOException> list = new ListBuffer<>();
+        fileSystems.forEach((p, fs) -> {
+            try {
+                fs.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"
     public void update(Log log, Lint lint, FSInfo fsInfo) {
         this.log = log;
@@ -329,15 +359,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) {
+            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;
 
@@ -349,37 +438,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);
@@ -400,12 +475,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 {
@@ -424,15 +499,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);
+                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;
 
@@ -451,12 +543,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);
@@ -476,8 +568,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 {
 
@@ -487,7 +579,7 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             lazy();
             return searchPath;
         }
@@ -524,19 +616,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);
@@ -592,13 +687,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 {
@@ -699,16 +794,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()) {
+                if (!s.isEmpty() && !s.endsWith(".jimage")) {
                     paths.add(Paths.get(s));
                 }
             }
@@ -728,6 +825,490 @@
         }
     }
 
+    /**
+     * A LocationHander to represent modules found from a module-oriented
+     * location such as MODULE_SOURCE_PATH, UPGRADE_MODULE_PATH,
+     * SYSTEM_MODULE_PATH and MODULE_PATH.
+     */
+    private class ModuleLocationHandler extends LocationHandler implements Location {
+        protected final String name;
+        protected final String moduleName;
+        protected final Collection<Path> searchPath;
+        protected final boolean output;
+
+        ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath, boolean output) {
+            this.name = name;
+            this.moduleName = moduleName;
+            this.searchPath = searchPath;
+            this.output = output;
+        }
+
+        @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() {
+            return searchPath;
+        }
+
+        @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 Iterable<Set<Location>>() {
+                @Override
+                public Iterator<Set<Location>> iterator() {
+                    return new ModulePathIterator();
+                }
+            };
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> paths) {
+            if (paths != null) {
+                for (Path p: paths) {
+                    if (!Files.isDirectory(p))
+                        throw new IllegalArgumentException(p.toString());
+                }
+            }
+            super.setPaths(paths);
+        }
+
+        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)) {
+                            Set<Location> result = new LinkedHashSet<>();
+                            try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
+                                int index = 0;
+                                for (Path entry : stream) {
+                                    Pair<String,Path> module = inferModuleName(entry);
+                                    if (module == null) {
+                                        // could add diagnostic here about bad item in directory
+                                        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);
+                                    result.add(l);
+                                }
+                            } catch (DirectoryIteratorException | IOException ignore) {
+                                // report diagnostic?
+                            }
+                            next = result;
+                            pathIndex++;
+                        } else {
+                            // could add diagnostic here about bad item on path
+                        }
+                    } 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 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)) {
+                        ClassFile cf = ClassFile.read(fs.getPath("module-info.class"));
+                        String className = cf.getName();
+                        String MODULE_INFO = "/module-info";
+                        if (className.endsWith(MODULE_INFO)) {
+                            String moduleName = className
+                                    .substring(0, className.length() - MODULE_INFO.length())
+                                    .replace('/', '.');
+                            return new Pair<>(moduleName, p);
+                        }
+                    } catch (IOException ignore) {
+                    } catch (ConstantPoolException ignore) {
+                    }
+                    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 {
+                                ClassFile cf = ClassFile.read(fs.getPath("classes/module-info.class"));
+                                String className = cf.getName();
+                                String MODULE_INFO = "/module-info";
+                                if (className.endsWith(MODULE_INFO)) {
+                                    String moduleName = className
+                                            .substring(0, className.length() - MODULE_INFO.length())
+                                            .replace('/', '.');
+                                    fileSystems.put(p, fs);
+                                    Path modulePath = fs.getPath("classes");
+                                    fs = null; // prevent fs being closed in the finally clause
+                                    return new Pair<>(moduleName, modulePath);
+                                }
+                            } finally {
+                                if (fs != null)
+                                    fs.close();
+                            }
+                        }
+                    } catch (IOException ignore) {
+                    } catch (ConstantPoolException ignore) {
+                    }
+                }
+
+                return null;
+            }
+        }
+    }
+
+    private class ModuleSourcePathLocationHandler extends BasicLocationHandler {
+
+        private final Map<String, Location> moduleLocations;
+        private final Map<Path, Location> pathLocations;
+
+
+        ModuleSourcePathLocationHandler() {
+            super(StandardLocation.MODULE_SOURCE_PATH,
+                    Option.MODULESOURCEPATH);
+            moduleLocations = new LinkedHashMap<>();
+            pathLocations = new LinkedHashMap<>();
+        }
+
+        @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);
+                    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);
+                    } else {
+                        suffix = Paths.get(seg.substring(markEnd + 1));
+                    }
+                    add(map, prefix, suffix);
+                }
+            }
+
+            moduleLocations.clear();
+            pathLocations.clear();
+            map.forEach((k, v) -> {
+                String name = location.getName() + "[" + k + "]";
+                ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false);
+                moduleLocations.put(k, h);
+                v.forEach(p -> pathLocations.put(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) {
+
+            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?
+            }
+        }
+
+        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.isEmpty();
+        }
+
+        @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.get(name);
+        }
+
+        @Override
+        Location getModuleLocation(Path dir) {
+            return pathLocations.get(dir);
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() {
+            Set<Location> locns = new LinkedHashSet<>();
+            moduleLocations.forEach((k, v) -> locns.add(v));
+            return Collections.singleton(locns);
+        }
+
+    }
+
+    private class SystemModulePathLocationHandler extends BasicLocationHandler {
+        private Path javaHome;
+        private Path modules;
+
+        SystemModulePathLocationHandler() {
+            super(StandardLocation.SYSTEM_MODULE_PATH, Option.SYSTEMMODULEPATH);
+            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) {
+            // for now, the only valid value is currently active JDK.
+            Path jh = Paths.get(System.getProperty("java.home"));
+            try {
+                if (!Files.isSameFile(p, jh))
+                    throw new IllegalArgumentException(p.toString());
+                javaHome = jh;
+                modules = null;
+            } catch (IOException ex) {
+                throw new IllegalArgumentException(p.toString(), ex);
+            }
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() throws IOException {
+            if (javaHome == null)
+                return Collections.emptyList();
+
+            if (modules == null) {
+                try {
+                    FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
+                    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);
+                }
+            }
+
+            Set<Location> systemModules = new LinkedHashSet<>();
+            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);
+                    systemModules.add(h);
+                }
+            }
+
+            return Collections.singleton(systemModules);
+        }
+    }
+
     Map<Location, LocationHandler> handlersForLocation;
     Map<Option, LocationHandler> handlersForOption;
 
@@ -735,17 +1316,21 @@
         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 OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
+            new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
+            new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
+            new ModuleSourcePathLocationHandler(),
+            new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADEMODULEPATH),
+            new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULEPATH, Option.MP),
+            new SystemModulePathLocationHandler(),
         };
 
-        for (LocationHandler h : handlers) {
+        for (BasicLocationHandler h : handlers) {
             handlersForLocation.put(h.location, h);
             for (Option o : h.options) {
                 handlersForOption.put(o, h);
@@ -758,9 +1343,14 @@
         return (h == null ? false : h.handleOption(option, value));
     }
 
+    boolean hasLocation(Location location) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : 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) {
@@ -781,12 +1371,34 @@
             }
             handlersForLocation.put(location, h);
         }
-        h.setLocation(files);
+        h.setPaths(files);
+    }
+
+    Location getModuleLocation(Location location, String name) {
+        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);
     }
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Thu Apr 02 18:57:23 2015 -0700
@@ -41,6 +41,7 @@
 import javax.tools.JavaFileObject;
 
 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.*;
@@ -101,6 +102,10 @@
      */
     boolean allowSimplifiedVarargs;
 
+    /** Switch: allow modules.
+     */
+    boolean allowModules;
+
    /** Lint option: warn about classfile issues
      */
     boolean lintClassfile;
@@ -146,6 +151,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];
@@ -218,6 +227,7 @@
 
         Source source = Source.instance(context);
         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
+        allowModules     = source.allowModules();
 
         saveParameterNames = options.isSet("save-parameter-names");
 
@@ -468,7 +478,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)));
     }
 
@@ -512,6 +522,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
  ***********************************************************************/
@@ -650,7 +688,7 @@
             switch (c) {
 
             case ';': {         // end
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
 
@@ -664,7 +702,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) {
@@ -727,7 +765,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);
@@ -971,25 +1009,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;
@@ -1120,12 +1139,111 @@
                 }
             },
 
-
             // 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(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);
+
+                        ListBuffer<UsesDirective> uses = new ListBuffer<>();
+                        int nuses = nextChar();
+                        for (int i = 0; i < nuses; i++) {
+                            ClassSymbol srvc = readClassSymbol(nextChar());
+                            uses.add(new UsesDirective(srvc));
+                        }
+                        msym.uses = uses.toList();
+                        directives.addAll(msym.uses);
+
+                        ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
+                        int nprovides = nextChar();
+                        for (int i = 0; i < nprovides; i++) {
+                            ClassSymbol srvc = readClassSymbol(nextChar());
+                            ClassSymbol impl = readClassSymbol(nextChar());
+                            provides.add(new ProvidesDirective(srvc, impl));
+                        }
+                        msym.provides = provides.toList();
+                        directives.addAll(msym.provides);
+
+                        msym.directives = directives.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)
@@ -1139,8 +1257,6 @@
             printCCF("ccf.unrecognized.attribute", attrName);
     }
 
-
-
     protected void readEnclosingMethodAttr(Symbol sym) {
         // sym is a nested class with an "Enclosing Method" attribute
         // remove sym from it's current owners scope and place it in
@@ -1366,7 +1482,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);
     }
 
@@ -2158,6 +2274,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.
      */
@@ -2173,14 +2297,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
+            ClassSymbol self = readClassSymbol(nextChar());
+            if (c != self) {
+                throw badClassFile("class.file.wrong.class",
+                                   self.flatname);
+            }
+            currentModule = c.packge().modle;
+        } 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
@@ -2237,7 +2374,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)
@@ -2393,6 +2530,10 @@
     }
 
     long adjustClassFlags(long flags) {
+        if ((flags & ACC_MODULE) != 0) {
+            flags &= ~ACC_MODULE;
+            flags |= MODULE;
+        }
         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
@@ -52,6 +54,7 @@
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.main.Option.*;
+
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 /** This class provides operations to map an internal symbol table graph
@@ -108,6 +111,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.
      */
@@ -956,6 +965,54 @@
     }
 
 /**********************************************************************
+ * Writing module attributes
+ **********************************************************************/
+
+    /** Write the Module attribute if needed.
+     *  Returns the number of attributes written (0 or 1).
+     */
+    int writeModuleAttribute(ClassSymbol c) {
+        ModuleSymbol m = c.modle;
+
+        int alenIdx = writeAttr(names.Module);
+        List<RequiresDirective> requires = m.requires;
+        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
  **********************************************************************/
 
@@ -1583,9 +1640,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.modle != null) ? c.modle : 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();
@@ -1623,11 +1688,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();
@@ -1712,6 +1783,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);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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.modle != null) ? c.modle : 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);
+        }
     }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -34,6 +34,7 @@
 
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
 
 import com.sun.tools.doclint.DocLint;
 import com.sun.tools.javac.code.Lint.LintCategory;
@@ -429,6 +430,26 @@
             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.EXTDIRS, Option.ENDORSEDDIRS);
+
+        checkOptionAllowed(t.compareTo(Target.JDK1_9) >= 0,
+                option -> error("err.option.not.allowed.with.target", option.getText(), t.name),
+                Option.MODULESOURCEPATH, Option.UPGRADEMODULEPATH,
+                Option.SYSTEMMODULEPATH, Option.MODULEPATH);
+
+        if (!options.isSet(Option.PROC, "only")) {
+            JavaFileManager fm = getFileManager();
+            if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)
+                    && !fm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                log.error("no.output.dir");
+            }
+        }
+
         if (obsoleteOptionFound)
             log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
 
@@ -528,6 +549,19 @@
         return true;
     }
 
+    private interface ErrorReporter {
+        void report(Option o);
+    }
+
+    void checkOptionAllowed(boolean allowed, ErrorReporter r, Option... opts) {
+        if (!allowed) {
+            for (Option o: opts) {
+                if (options.isSet(o))
+                    r.report(o);
+            }
+        }
+    }
+
     void error(String key, Object... args) {
         errors = true;
         switch (errorMode) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -766,7 +766,12 @@
             boolean isPkgInfo =
                 tree.sourcefile.isNameCompatible("package-info",
                                                  JavaFileObject.Kind.SOURCE);
-            if (isPkgInfo) {
+            boolean isModuleInfo =
+                tree.sourcefile.isNameCompatible("module-info",
+                                                 JavaFileObject.Kind.SOURCE);
+            if (isModuleInfo) {
+                // TODO: INSERT CHECK HERE
+            } else if (isPkgInfo) {
                 if (enter.getEnv(tree.packge) == null) {
                     JCDiagnostic diag =
                         diagFactory.fragment("file.does.not.contain.package",
@@ -1414,14 +1419,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 (!(stubOutput || sourceOutput || printFlat)) {
                     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));
+                    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;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -140,7 +140,11 @@
         Result result = compile(args, context);
         if (fileManager instanceof JavacFileManager) {
             // A fresh context was created above, so jfm must be a JavacFileManager
-            ((JavacFileManager)fileManager).close();
+            try {
+                ((JavacFileManager)fileManager).close();
+            } catch (IOException ex) {
+                bugMessage(ex);
+            }
         }
         return result;
     }
@@ -199,11 +203,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
@@ -214,7 +220,7 @@
             showClass(showClass);
         }
 
-        boolean ok = args.validate();
+        ok &= args.validate();
         if (!ok || log.nerrors > 0)
             return Result.CMDERR;
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, 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
@@ -176,6 +176,21 @@
 
     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),
+
+    SYSTEMMODULEPATH("-systemmodulepath", "opt.arg.jdk", "opt.systemmodulepath", STANDARD, FILEMANAGER),
+
     BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) {
         @Override
         public boolean process(OptionHelper helper, String option, String arg) {
@@ -476,6 +491,16 @@
         }
     },
 
+    XXADDMODULEEXPORTS("-XX:AddModuleExports=", null, HIDDEN, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            String p = option.substring(option.indexOf('=') + 1);
+            String prev = helper.get(XXADDMODULEEXPORTS);
+            helper.put(XXADDMODULEEXPORTS.text, (prev == null) ? p : prev + ' ' + p.trim());
+            return false;
+        }
+    },
+
     // 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) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Apr 02 18:57:23 2015 -0700
@@ -157,6 +157,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();
@@ -205,6 +206,10 @@
      */
     boolean allowMethodReferences;
 
+    /** Switch: should we recognize modules?
+     */
+    boolean allowModules;
+
     /** Switch: should we allow default methods in interfaces?
      */
     boolean allowDefaultMethods;
@@ -3052,59 +3057,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;
+
+        if (token.kind == IDENTIFIER && token.name() == names.module) {
+            defs.append(moduleDecl(token.comment(CommentStyle.JAVADOC)));
+            consumedToplevelDoc = true;
+        } 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);
             }
-            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;
+            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;
                 }
-                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;
+                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));
@@ -3119,6 +3130,75 @@
         return toplevel;
     }
 
+    JCModuleDecl moduleDecl(Comment dc) {
+        int pos = token.pos;
+        if (!allowModules) {
+            log.error(pos, "modules.not.supported.in.source", 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() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Apr 02 18:57:23 2015 -0700
@@ -1,4 +1,3 @@
-
 #
 # Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -797,8 +796,8 @@
     {0} is not an annotation type
 
 # 0: symbol, 1: symbol
-compiler.err.not.def.access.class.intf.cant.access=\
-    {0} in {1} is defined in an inaccessible class or interface
+compiler.err.not.def.access.package.cant.access=\
+    {0} is not visible because package {1} is not visible
 
 # 0: symbol, 1: symbol
 compiler.misc.not.def.access.class.intf.cant.access=\
@@ -1758,6 +1757,9 @@
 compiler.misc.unnamed.package=\
     unnamed package
 
+compiler.misc.unnamed.module=\
+    unnamed module
+
 #####
 
 # 0: symbol, 1: message segment
@@ -1814,6 +1816,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}
 
@@ -2618,4 +2623,66 @@
 compiler.err.dc.unterminated.string=\
     unterminated string
 
-
+###
+# errors related to modules
+
+# 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}
+
+compiler.err.no.output.dir=\
+    no class output directory specified
+
+compiler.err.cant.determine.module=\
+    cannot determine module on module source path
+
+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
+
+# 0: symbol
+compiler.err.cyclic.requires=\
+    cyclic dependence involving {0}
+
+# 0: fragment, 1: string
+compiler.err.duplicate.module.on.path=\
+    duplicate module on {0}\nmodule in {1}
+
+compiler.misc.locn.module_source_path=\
+    module source path
+
+compiler.misc.locn.upgrade_module_path=\
+    upgrade module path
+
+compiler.misc.locn.system_module_path=\
+    system module path
+
+compiler.misc.locn.module_path=\
+    application module path
+
+compiler.misc.cant.resolve.modules=\
+    cannot resolve modules
+
+###
+# errors related to options
+
+# 0; string, 1: string
+compiler.err.illegal.argument.for.option=\
+    illegal argument for {0}: {1}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -276,6 +276,8 @@
     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.no.source.files=\
     no source files
 javac.err.no.source.files.classes=\
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -37,14 +37,20 @@
 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 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.
@@ -346,6 +352,12 @@
         DIV_ASG(DIV),                    // /=
         MOD_ASG(MOD),                    // %=
 
+        MODULEDEF,
+        EXPORTS,
+        PROVIDES,
+        REQUIRES,
+        USES,
+
         /** A synthetic let expression, of type LetExpr.
          */
         LETEXPR;                         // ala scheme
@@ -486,8 +498,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. */
@@ -2601,8 +2617,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;
@@ -2739,6 +2949,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, JCTree expr);
     }
 
@@ -2799,6 +3014,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(); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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 ");
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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.
  *
@@ -1144,4 +1145,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);
+    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -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;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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);
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -42,6 +42,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;
@@ -208,7 +209,26 @@
      * @return true if successful, and false otherwise
      */
     public boolean handleOption(Option option, String value) {
-        return locations.handleOption(option, value);
+        if (options.isSet("jakeBuildWorkAround")) {
+            switch (option) {
+                case D: case H: // output directory options
+                    value = Paths.get(value).getParent().toString();
+                    System.err.println("javac: using " + option.text + ": " + value);
+                    break;
+                case MODULESOURCEPATH:
+                    System.err.println("javac: using " + option.text + ": " + value);
+                    break;
+            }
+        }
+
+        switch (option) {
+            case ENCODING:
+                options.put(option, value);
+                return true;
+
+            default:
+                return locations.handleOption(option, value);
+        }
     }
 
     /**
@@ -218,8 +238,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("illegal.argument.for.option", e.getKey().getText(), ex.getMessage());
+                ok = false;
+            }
+        }
         return ok;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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;
@@ -200,6 +213,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");
@@ -253,6 +273,9 @@
         // package names
         java_lang = fromString("java.lang");
 
+        // module names
+        java_base = fromString("java.base");
+
         // attribute names
         Annotation = fromString("Annotation");
         AnnotationDefault = fromString("AnnotationDefault");
@@ -271,6 +294,7 @@
         LocalVariableTable = fromString("LocalVariableTable");
         LocalVariableTypeTable = fromString("LocalVariableTypeTable");
         MethodParameters = fromString("MethodParameters");
+        Module = fromString("Module");
         RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
         RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
         RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
@@ -285,6 +309,7 @@
         Synthetic = fromString("Synthetic");
         Value = fromString("Value");
         Varargs = fromString("Varargs");
+        Version = fromString("Version");
 
         // members of java.lang.annotation.ElementType
         ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
@@ -307,6 +332,7 @@
         T = fromString("T");
         deprecated = fromString("deprecated");
         ex = fromString("ex");
+        module_info = fromString("module-info");
         package_info = fromString("package-info");
         requireNonNull = fromString("requireNonNull");
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javap/AttributeWriter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javap/AttributeWriter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -25,14 +25,13 @@
 
 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.ConstantPool;
@@ -42,11 +41,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 +63,7 @@
 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.Version_attribute;
 
 import static com.sun.tools.classfile.AccessFlags.*;
 
@@ -114,6 +118,7 @@
         }
     }
 
+    @Override
     public Void visitDefault(DefaultAttribute attr, Void ignore) {
         if (attr.reason != null) {
             report(attr.reason);
@@ -150,6 +155,7 @@
         return null;
     }
 
+    @Override
     public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) {
         println("AnnotationDefault:");
         indent(+1);
@@ -159,6 +165,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 +185,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 +223,19 @@
         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;
     }
 
+    @Override
     public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) {
         print("ConstantValue: ");
         constantWriter.write(attr.constantvalue_index);
@@ -233,11 +243,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 +276,7 @@
         }
     }
 
+    @Override
     public Void visitExceptions(Exceptions_attribute attr, Void ignore) {
         println("Exceptions:");
         indent(+1);
@@ -286,10 +299,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 +391,7 @@
         indent(+1);
     }
 
+    @Override
     public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) {
         println("LineNumberTable:");
         indent(+1);
@@ -348,6 +402,7 @@
         return null;
     }
 
+    @Override
     public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) {
         println("LocalVariableTable:");
         indent(+1);
@@ -362,6 +417,7 @@
         return null;
     }
 
+    @Override
     public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) {
         println("LocalVariableTypeTable:");
         indent(+1);
@@ -376,8 +432,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 +474,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 +562,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleAnnotations:");
         indent(+1);
@@ -424,6 +575,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleTypeAnnotations:");
         indent(+1);
@@ -436,6 +588,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleTypeAnnotations:");
         indent(+1);
@@ -448,6 +601,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleParameterAnnotations:");
         indent(+1);
@@ -465,6 +619,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleParameterAnnotations:");
         indent(+1);
@@ -482,6 +637,7 @@
         return null;
     }
 
+    @Override
     public Void visitSignature(Signature_attribute attr, Void ignore) {
         print("Signature: #" + attr.signature_index);
         tab();
@@ -497,6 +653,7 @@
         }
     }
 
+    @Override
     public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) {
         println("SourceDebugExtension:");
         indent(+1);
@@ -507,6 +664,7 @@
         return null;
     }
 
+    @Override
     public Void visitSourceFile(SourceFile_attribute attr, Void ignore) {
         println("SourceFile: \"" + getSourceFile(attr) + "\"");
         return null;
@@ -520,11 +678,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 +696,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 +714,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 +729,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 +739,7 @@
             return null;
         }
 
+        @Override
         public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) {
             printHeader(frame, "/* chop */");
             indent(+1);
@@ -583,6 +748,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 +757,7 @@
             return null;
         }
 
+        @Override
         public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) {
             printHeader(frame, "/* append */");
             indent(+1);
@@ -600,6 +767,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 +846,28 @@
         }
     }
 
+    @Override
     public Void visitSynthetic(Synthetic_attribute attr, Void ignore) {
         println("Synthetic: true");
         return null;
     }
 
+    @Override
+    public Void visitVersion(Version_attribute attr, Void ignore) {
+        print("Version: #" + attr.version_index);
+        tab();
+        println("// " + getVersion(attr));
+        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 +887,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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/module-info.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+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.javap;
+    exports com.sun.tools.classfile to
+        jdk.dev;
+    exports com.sun.tools.doclint to
+        jdk.javadoc;
+    exports com.sun.tools.javac.api to
+        jdk.javadoc;
+    exports com.sun.tools.javac.code to
+        jdk.javadoc;
+    exports com.sun.tools.javac.comp to
+        jdk.javadoc;
+    exports com.sun.tools.javac.file to
+        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.nio to
+        jdk.javadoc;
+    exports com.sun.tools.javac.sym to
+        jdk.javadoc;
+    exports com.sun.tools.javac.tree to
+        jdk.javadoc;
+    exports com.sun.tools.javac.util to
+        jdk.javadoc;
+}
+
--- a/src/jdk.dev/share/classes/com/sun/tools/jdeps/Module.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.dev/share/classes/com/sun/tools/jdeps/Module.java	Thu Apr 02 18:57:23 2015 -0700
@@ -30,6 +30,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import com.sun.tools.jdeps.ClassFileReader.ModuleClassReader;
 
 /**
  * JDeps internal representation of module for dependency analysis.
@@ -168,7 +169,6 @@
         }
 
         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;
         }
@@ -184,7 +184,7 @@
             exports.put(p, new HashSet<>(ms));
             return this;
         }
-        public Builder classes(ClassFileReader.ModuleClassReader reader) {
+        public Builder classes(ModuleClassReader reader) {
             this.reader = reader;
             return this;
         }
--- a/src/jdk.dev/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.dev/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java	Thu Apr 02 18:57:23 2015 -0700
@@ -34,8 +34,8 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.Attribute;
 import javax.xml.stream.events.XMLEvent;
+import com.sun.tools.jdeps.PlatformClassPath.ImageHelper;
 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)
--- a/src/jdk.dev/share/classes/com/sun/tools/jdeps/PlatformClassPath.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.dev/share/classes/com/sun/tools/jdeps/PlatformClassPath.java	Thu Apr 02 18:57:23 2015 -0700
@@ -97,29 +97,35 @@
     }
 
     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);
             }
-            Path home = Paths.get(System.getProperty("java.home"));
-            Path mlib = home.resolve("lib").resolve("modules");
-            if (Files.isDirectory(mlib)) {
-                // jimage
+            if (isJrtAvailable()) {
+                // jrt file system
                 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-                return new ImageHelper(fs, fs.getPath("/"));
+                return new ImageHelper(fs, fs.getPath("/modules"));
             } else {
                 // exploded modules
-                mlib = home.resolve("modules");
-                if (!Files.isDirectory(mlib)) {
+                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(mlib);
+                return new ImageHelper(exploded);
             }
         }
 
         private final FileSystem fs;
         private final Path mpath;
-
         ImageHelper(Path path) throws IOException {
             this(FileSystems.getDefault(), path);
         }
--- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -150,7 +150,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.javaBase, names.fromString("java.io.Externalizable"));
         chk = Check.instance(context);
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
--- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java	Thu Apr 02 18:57:23 2015 -0700
@@ -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
@@ -41,7 +41,6 @@
 import com.sun.javadoc.*;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.CommandLine;
-import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.util.BaseFileManager;
 import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.Context;
@@ -288,6 +287,11 @@
         // Make sure no obsolete source/target messages are reported
         compOpts.put("-Xlint:-options", "-Xlint:-options");
 
+        /*
+         *TEMPORARY: disable module processing for now in javadoc
+         */
+        compOpts.put("noModules", "true");
+
         // Parse arguments
         for (int i = 0 ; i < argv.length ; i++) {
             String arg = argv[i];
--- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,6 +88,34 @@
         }
     },
 
+    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);
+        }
+    },
+
+    SYSTEMMODULEPATH("-systemmodulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SYSTEMMODULEPATH, arg);
+        }
+    },
+
+    MODULEPATH("-modulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULEPATH, arg);
+        }
+    },
+
     ENCODING("-encoding", true) {
         @Override
         public void process(Helper helper, String arg) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/module-info.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+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;
+}
+
--- a/test/tools/javac/MethodParameters/AttributeVisitor.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/test/tools/javac/MethodParameters/AttributeVisitor.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -43,6 +43,7 @@
     public R visitLocalVariableTable(LocalVariableTable_attribute attr, P p) { return null; }
     public R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p) { return null; }
     public R visitMethodParameters(MethodParameters_attribute attr, P p) { return null; }
+    public R visitModule(Module_attribute attr, P p) { return null; }
     public R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p) { return null; }
     public R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p) { return null; }
     public R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p) { return null; }
--- a/test/tools/javac/lib/DPrinter.java	Mon Mar 30 16:38:59 2015 +0100
+++ b/test/tools/javac/lib/DPrinter.java	Thu Apr 02 18:57:23 2015 -0700
@@ -1280,6 +1280,10 @@
             return visitType(type, null);
         }
 
+        public Void visitModuleType(ModuleType type, Void ignore) {
+            return visitType(type, null);
+        }
+
         public Void visitPackageType(PackageType type, Void ignore) {
             return visitType(type, null);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/HelloWorldTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary simple tests of javac compilation modes
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main HelloWorldTest
+ */
+
+import java.nio.file.*;
+import javax.tools.*;
+
+public class HelloWorldTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        HelloWorldTest t = new HelloWorldTest();
+        t.runTests();
+    }
+
+    public static final String HELLO_WORLD =
+          "class HelloWorld {\n"
+        + "    public static void main(String... args) {\n"
+        + "        System.out.println(\"Hello World!\");\n"
+        + "    }\n"
+        + "}";
+
+    public static final String PKG_HELLO_WORLD =
+          "package p;\n"
+        + HELLO_WORLD;
+
+    @Test
+    void testLegacyMode(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        Path smallRtJar = base.resolve("small-rt.jar");
+        try (JavaFileManager fm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null)) {
+            tb.new JarTask(smallRtJar.toString())
+                .files(fm, StandardLocation.PLATFORM_CLASS_PATH,
+                    "java.lang.**", "java.io.*", "java.util.*")
+                .run();
+        }
+
+        tb.new JavacTask()
+            .options("-source", "8",
+                "-target", "8",
+                "-bootclasspath", smallRtJar.toString())
+            .outdir(classes.toString())
+            .files(src.resolve("HelloWorld.java"))
+            .run();
+
+        checkFiles(classes.resolve("HelloWorld.class"));
+    }
+
+    @Test
+    void testUnnamedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+            .outdir(classes.toString())
+            .files(src.resolve("HelloWorld.java"))
+            .run();
+
+        checkFiles(classes.resolve("HelloWorld.class"));
+    }
+
+    @Test
+    void testSingleModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "module m { }");
+        tb.writeJavaFiles(src, PKG_HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+            .outdir(classes.toString())
+            .files(src.resolve("module-info.java"), src.resolve("p/HelloWorld.java"))
+            .run()
+            .writeAll();
+
+        checkFiles(
+            classes.resolve("module-info.class"),
+            classes.resolve("p/HelloWorld.class"));
+    }
+
+    @Test
+    void testModuleSourcePath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
+        tb.writeJavaFiles(src_m1, PKG_HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+            .options("-modulesourcepath", src.toString())
+            .outdir(classes.toString())
+            .files(src_m1.resolve("p/HelloWorld.java"))
+            .run()
+            .writeAll();
+
+        checkFiles(
+            classes.resolve("m1/module-info.class"),
+            classes.resolve("m1/p/HelloWorld.class"));
+    }
+
+    void checkFiles(Path... files) throws Exception {
+        for (Path f: files) {
+            if (!Files.exists(f))
+                throw new Exception("expected file not found: " + f);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ModuleFinderTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main ModuleFinderTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ModuleFinderTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        ModuleFinderTest t = new ModuleFinderTest();
+        t.runTests();
+    }
+
+    @Test
+    void testDuplicateModulesOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m1 { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        tb.new JarTask(modules.resolve("m1-1.jar").toString()) // should allow Path here
+                .baseDir(classes.toString()) // should allow Path here
+                .files(".")
+                .run();
+
+        tb.new JarTask(modules.resolve("m1-2.jar").toString()) // should allow Path here
+                .baseDir(classes.toString()) // should allow Path here
+                .files(".")
+                .run();
+
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2, "module m2 { requires m1; }");
+
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics", "-modulepath", modules.toString())
+                .outdir(classes.toString())
+                .files(findJavaFiles(src2))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.duplicate.module.on.path: (compiler.misc.locn.module_path), m1"))
+            throw new Exception("expected output not found");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ModuleInfoTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main ModuleInfoTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ModuleInfoTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        ModuleInfoTest t = new ModuleInfoTest();
+        t.runTests();
+    }
+
+    /**
+     * Check error message if module declaration not in module-info.java.
+     */
+    @Test
+    void testModuleDeclNotInModuleJava(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("M.java"), "module M { }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("M.java:1:1: compiler.err.module.decl.sb.in.module-info.java"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a package private class can be put in module-info.java.
+     */
+    @Test
+    void testNotModuleDeclInModuleJava_1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "class C { }");
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    /**
+     * Verify that a public class cannot be put in module-info.java.
+     */
+    @Test
+    void testNotModuleDeclInModuleJava_2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "public class C { }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:8: compiler.err.class.public.should.be.in.file: C"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that only one module decl can be put in module-info.java.
+     */
+    @Test
+    void testSingleModuleDecl(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M1 { } /*...*/ module M2 { }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:14: compiler.err.expected: token.end-of-input"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that missing requires are reported.
+     */
+    @Test
+    void testRequiresNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M1 { requires M2; }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:22: compiler.err.module.not.found: M2"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that missing exports are reported.
+     */
+    @Test
+    void testExportsNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M1 { exports p to M2; }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:26: compiler.err.module.not.found: M2"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a simple loop is detected.
+     */
+    @Test
+    void testRequiresSelf(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M { requires M; }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:21: compiler.err.cyclic.requires: M"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a multi-module loop is detected.
+     */
+    @Test
+    void testRequiresLoop(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires m3; }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:22: compiler.err.cyclic.requires: m2"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that duplicate requires are detected.
+     */
+    @Test
+    void testDuplicateRequires(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires m1; requires m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:35: compiler.err.duplicate.requires: m1"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that duplicate exported packages are detected.
+     */
+    @Test
+    void testDuplicateExports_packages(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m1 { exports p; exports p; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:32: compiler.err.duplicate.exports: p"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that duplicate exported packages are detected.
+     */
+    @Test
+    void testDuplicateExports_modules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { exports p to m1, m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:30: compiler.err.duplicate.exports: m1"))
+            throw new Exception("expected output not found");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ModulePathTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main ModulePathTest
+ */
+
+import java.nio.file.Path;
+
+public class ModulePathTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        ModulePathTest t = new ModulePathTest();
+        t.runTests();
+    }
+
+    @Test
+    void testNotExistsOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "doesNotExist")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.illegal.argument.for.option: -modulepath, doesNotExist"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testNotADirOnPath_1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+        tb.writeFile("dummy.jar", "");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "dummy.jar")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.illegal.argument.for.option: -modulepath, dummy.jar"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testNotADirOnPath_2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+        tb.writeFile("dummy.txt", "");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "dummy.txt")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.illegal.argument.for.option: -modulepath, dummy.txt"))
+            throw new Exception("expected output not found");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ModuleTestBase.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class for module tests.
+ */
+class ModuleTestBase {
+    protected ToolBox tb;
+    protected PrintStream out;
+    private int errors;
+
+    /** Marker annotation for test methods to be invoked by runTests. */
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Test { }
+
+    /**
+     * Run all methods annotated with @Test, and throw an exception if any
+     * errors are reported..
+     * @throws Exception if any errors occurred
+     */
+    void runTests() throws Exception {
+        if (tb == null)
+            tb = new ToolBox();
+        out = System.err;
+
+        for (Method m: getClass().getDeclaredMethods()) {
+            Annotation a = m.getAnnotation(Test.class);
+            if (a != null) {
+                try {
+                    out.println("Running test " + m.getName());
+                    Path baseDir = Paths.get(m.getName());
+                    m.invoke(this, new Object[] { baseDir });
+                } catch (InvocationTargetException e) {
+                    Throwable cause = e.getCause();
+                    error("Exception: " + e.getCause());
+                    cause.printStackTrace(out);
+                }
+                out.println();
+            }
+        }
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    // move to ToolBox?
+    // change returntyp to List<Path> -- means updating ToolBox methods
+    Path[] findJavaFiles(Path p) throws IOException {
+        List<Path> list = new ArrayList<>();
+        Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                    throws IOException {
+                if (file.getFileName().toString().endsWith(".java")) {
+                    list.add(file);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+        });
+        return list.toArray(new Path[list.size()]);
+    }
+
+    void error(String message) {
+        out.println("Error: " + message);
+        errors++;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/MultiModuleModeTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main MultiModuleModeTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MultiModuleModeTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new MultiModuleModeTest().runTests();
+    }
+
+    @Test
+    void testDuplicateModules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2, "module m1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .outdir(classes.toString()) // should allow Path here
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:1: compiler.err.duplicate.module: m1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testCantFindModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m1 { }");
+        Path misc = base.resolve("misc");
+        tb.writeJavaFiles(misc, "package p; class C { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .outdir(classes.toString()) // should allow Path here
+                .files(join(findJavaFiles(src), findJavaFiles(misc)))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:1: compiler.err.cant.determine.module"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testImplicitModuleSource(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
+        tb.writeJavaFiles(src.resolve("m2"), "module m2 { requires m1; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should allow Path here
+                .files(src.resolve("m2/module-info.java"))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testImplicitModuleClass(Path base) throws Exception {
+        Path src1 = base.resolve("src1");
+        tb.writeJavaFiles(src1.resolve("m1"), "module m1 { }");
+        Path modules1 = base.resolve("modules1");
+        Files.createDirectories(modules1);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src1.toString())
+                .outdir(modules1.toString()) // should allow Path here
+                .files(src1.resolve("m1/module-info.java"))
+                .run()
+                .writeAll();
+
+        Path src2= base.resolve("src2");
+        tb.writeJavaFiles(src2.resolve("m2"), "module m2 { requires m1; }");
+        Path modules2 = base.resolve("modules2");
+        Files.createDirectories(modules2);
+
+        tb.new JavacTask()
+                .options("-modulepath", modules1.toString(),
+                        "-modulesourcepath", src2.toString())
+                .outdir(modules2.toString()) // should allow Path here
+                .files(src2.resolve("m2/module-info.java"))
+                .run()
+                .writeAll();
+    }
+
+    Path[] join(Path[] a, Path[] b) {
+        List<Path> result = new ArrayList<>();
+        result.addAll(Arrays.asList(a));
+        result.addAll(Arrays.asList(b));
+        return result.toArray(new Path[result.size()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/OutputDirTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main OutputDirTest
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class OutputDirTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new OutputDirTest().run();
+    }
+
+    Path src;
+
+    void run() throws Exception {
+        tb = new ToolBox();
+
+        src = Paths.get("src");
+        tb.writeJavaFiles(src.resolve("m"),
+                "module m { }",
+                "package p; class C { }");
+
+        runTests();
+    }
+
+    @Test
+    void testError(Path base) throws Exception {
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.no.output.dir"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testProcOnly(Path base) throws IOException {
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-proc:only",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testClassOutDir(Path base) throws IOException {
+        Path classes = base.resolve("classes");
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-d", classes.toString(),
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ProvidesTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary simple tests of module provides
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main ProvidesTest
+ */
+
+import java.nio.file.*;
+
+public class ProvidesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ProvidesTest t = new ProvidesTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testMulti(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; provides p1.C1 with p2.C2; }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+    }
+
+    @Test
+    void testMissingWith(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.C; }",
+                "package p; public class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:24: compiler.err.expected: 'with'"))
+            throw new Exception("expected output not found");
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/RequiresPublicTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main RequiresPublicTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class RequiresPublicTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        RequiresPublicTest t = new RequiresPublicTest();
+        t.runTests();
+    }
+
+    @Test
+    void testJavaSE_OK(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires java.se; }",
+                "import java.awt.Frame;\n"  // in java.se
+                + "class Test {\n"
+                + "    Frame f;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .files(findJavaFiles(src))
+                .outdir(classes.toString()) // should allow Path here
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testJavaSE_Fail(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires java.se; }",
+                "import com.sun.source.tree.Tree;\n" // not in java.se (in jdk.compiler)
+                + "class Test {\n"
+                + "    Tree t;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .outdir(classes.toString()) // should allow Path here
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("Test.java:1:27: compiler.err.doesnt.exist: com.sun.source.tree"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testComplex_OK(Path base) throws Exception {
+        Path src = getComplexSrc(base, "", "");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes.toString()) // should allow Path here
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testComplex_Fail(Path base) throws Exception {
+        Path src = getComplexSrc(base,
+                "import p5.C5; import p6.C6; import p7.C7;\n",
+                "C5 c5; C6 c6; C7 c7;\n");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes.toString()) // should allow Path here
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        String[] expect = {
+            "C1.java:5:10: compiler.err.not.def.access.package.cant.access: p5.C5, p5",
+            "C1.java:5:24: compiler.err.not.def.access.package.cant.access: p6.C6, p6",
+            "C1.java:5:38: compiler.err.not.def.access.package.cant.access: p7.C7, p7",
+            "C1.java:8:1: compiler.err.cant.resolve.location: kindname.class, C5, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:8: compiler.err.cant.resolve.location: kindname.class, C6, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:15: compiler.err.cant.resolve.location: kindname.class, C7, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)"
+        };
+
+        for (String e: expect) {
+            if (!log.contains(e))
+                throw new Exception("expected output not found: " + e);
+        }
+    }
+
+    /*
+     * Set up the following module graph
+     *     m1 -> m2 => m3 => m4 -> m5
+     *              -> m6 => m7
+     * where -> is requires, => is requires public
+     */
+    Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
+        Path src = base.resolve("src");
+
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                "module m1 { requires m2; }",
+                "package p1;\n"
+                + "import p2.C2;\n"
+                + "import p3.C3;\n"
+                + "import p4.C4;\n"
+                + m1_extraImports
+                + "class C1 {\n"
+                + "  C2 c2; C3 c3; C4 c4;\n"
+                + m1_extraUses
+                + "}\n");
+
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                "module m2 {\n"
+                + "  requires public m3;\n"
+                + "  requires        m6;\n"
+                + "  exports p2;\n"
+                + "}",
+                "package p2;\n"
+                + "public class C2 { }\n");
+
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                "module m3 { requires public m4; exports p3; }",
+                "package p3;\n"
+                + "public class C3 { }\n");
+
+        Path src_m4 = src.resolve("m4");
+        tb.writeJavaFiles(src_m4,
+                "module m4 { requires m5; exports p4; }",
+                "package p4;\n"
+                + "public class C4 { }\n");
+
+        Path src_m5 = src.resolve("m5");
+        tb.writeJavaFiles(src_m5,
+                "module m5 { exports p5; }",
+                "package p5;\n"
+                + "public class C5 { }\n");
+
+        Path src_m6 = src.resolve("m6");
+        tb.writeJavaFiles(src_m6,
+                "module m6 { requires public m7; exports p7; }",
+                "package p6;\n"
+                + "public class C6 { }\n");
+
+        Path src_m7 = src.resolve("m7");
+        tb.writeJavaFiles(src_m7,
+                "module m7 { exports p7; }",
+                "package p7;\n"
+                + "public class C7 { }\n");
+
+        return src;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ResolveTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary simple tests of javac compilation modes
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main ResolveTest
+ */
+
+import java.nio.file.*;
+
+public class ResolveTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ResolveTest t = new ResolveTest();
+        t.runTests();
+    }
+
+    @Test
+    void testMissingSimpleTypeUnnamedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { D d; }");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:11: compiler.err.cant.resolve.location: "
+                + "kindname.class, D, , , (compiler.misc.location: kindname.class, C, null)"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testMissingSimpleTypeNamedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { }",
+                "class C { D d; }");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:11: compiler.err.cant.resolve.location: "
+                + "kindname.class, D, , , (compiler.misc.location: kindname.class, C, null)"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testUnexportedTypeUnreadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should accept Path here
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testUnexportedTypeReadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should accept Path here
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testQualifiedExportedTypeReadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1 to m3; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        tb.writeJavaFiles(src.resolve("m3"),
+                "module m3 { requires m1; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should accept Path here
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testExportedTypeUnreadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should accept Path here
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testExportedTypeReadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should accept Path here
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testExportedTypeReadableModule2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1 to m2; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules.toString()) // should accept Path here
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/SingleModuleModeTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main SingleModuleModeTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class SingleModuleModeTest extends ModuleTestBase{
+
+    public static void main(String... args) throws Exception {
+        new SingleModuleModeTest().run();
+    }
+
+    void run() throws Exception {
+        tb = new ToolBox();
+
+        runTests();
+    }
+
+    @Test
+    void testTooManyModules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
+        tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:1: compiler.err.too.many.modules"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testImplicitModuleSource(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { }",
+                "class C { }");
+
+        tb.new JavacTask()
+                .classpath(src.toString()) // should allow Path here
+                .files(src.resolve("C.java"))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testImplicitModuleClass(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes.toString()) // should allow Path here
+                .files(src.resolve("module-info.java"))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .classpath(classes.toString()) // should allow Path here
+                .files(src.resolve("C.java"))
+                .run()
+                .writeAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/SubpackageTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main SubpackageTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SubpackageTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        SubpackageTest t = new SubpackageTest();
+        t.runTests();
+    }
+
+    @Test // based on JDK-8075435
+    void testUnnamedModule(Path base) throws Exception {
+        Path libsrc = base.resolve("lib/src");
+        tb.writeJavaFiles(libsrc,
+            "package p; public class E extends Error { }");
+        Path libclasses = base.resolve("lib/classes");
+        Files.createDirectories(libclasses);
+        tb.new JavacTask()
+                .outdir(libclasses.toString())
+                .files(findJavaFiles(libsrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+            "package p.q;\n"
+            + "import p.E;\n"
+            + "class Test {\n"
+            + "  void m() { throw new E(); }\n"
+            + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .classpath(libclasses.toString())
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testSimpleMulti(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("mp"),
+                "module mp { exports p; }",
+                "package p; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("mpq"),
+                "module mpq { exports p.q; }",
+                "package p.q; public class C2 { }");
+        tb.writeJavaFiles(src.resolve("mpqr"),
+                "module mpqr { exports p.q.r; }",
+                "package p.q.r; public class C3 { }");
+        tb.writeJavaFiles(src.resolve("m"),
+                "module m {"
+                + "  requires mp;\n"
+                + "  requires mpq;\n"
+                + "  requires mpqr;\n"
+                + "}",
+                "package x;\n"
+                + "class C {\n"
+                + "  p.C1 c1;\n"
+                + "  p.q.C2 c2;\n"
+                + "  p.q.r.C3 c3;\n"
+                + "}");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/UsesTest.java	Thu Apr 02 18:57:23 2015 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary simple tests of module uses
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main UsesTest
+ */
+
+import java.nio.file.*;
+
+public class UsesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        UsesTest t = new UsesTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p.C; }",
+                "package p; public class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))