changeset 4285:4af8cb38c00f

Adjusting weak modules according to the current proposal; dropping exports dynamic, exports default.
author jlahoda
date Tue, 06 Sep 2016 11:50:40 +0200
parents 4db263f9343d
children df338e714f64
files src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java test/tools/javac/classfiles/attributes/Module/ModuleTest.java test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java test/tools/javac/diags/examples/ConflictingDefaultExports/module-info.java test/tools/javac/diags/examples/DefaultExportsMustBeDynamic/module-info.java test/tools/javac/diags/examples/ExpectedIdentifierOrDefault/module-info.java test/tools/javac/diags/examples/NoExportsInWeak/module-info.java test/tools/javac/modules/ModuleInfoTest.java test/tools/javac/modules/PackageConflictTest.java test/tools/javac/modules/ReportNonExistentPackageTest.java test/tools/javac/modules/WeakModulesTest.java
diffstat 29 files changed, 388 insertions(+), 452 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java	Tue Sep 06 11:50:40 2016 +0200
@@ -150,11 +150,6 @@
      * @since 9
      */
     interface ExportsDirective extends Directive {
-        /**
-         * Returns whether or not this is a dynamic exports.
-         * @return whether or not this is a dynamic exports
-         */
-        boolean isDynamic();
 
         /**
          * Returns whether or not this is a private exports.
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java	Tue Sep 06 11:50:40 2016 +0200
@@ -41,11 +41,6 @@
  * @since 9
  */
 public interface ExportsTree extends DirectiveTree {
-    /**
-     * Returns true if this is a "exports dynamic" directive.
-     * @return true if this is a "exports dynamic" directive
-     */
-    boolean isDynamic();
 
     /**
      * Returns true if this is a "exports private" directive.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Tue Sep 06 11:50:40 2016 +0200
@@ -76,7 +76,6 @@
 
     /** Flags for ExportsDirective. */
     public enum ExportsFlag {
-        DYNAMIC_PHASE(0x0040),
         REFLECTION(0x0080),
         SYNTHETIC(0x1000),
         MANDATED(0x8000);
@@ -121,11 +120,6 @@
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public boolean isDynamic() {
-            return flags.contains(ExportsFlag.DYNAMIC_PHASE);
-        }
-
-        @Override @DefinedBy(Api.LANGUAGE_MODEL)
         public boolean isPrivate() {
             return flags.contains(ExportsFlag.REFLECTION);
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Sep 06 11:50:40 2016 +0200
@@ -27,7 +27,9 @@
 
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Inherited;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -47,6 +49,7 @@
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.ClassFinder.BadEnclosingMethodAttr;
+import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -897,9 +900,11 @@
 
         public PackageSymbol unnamedPackage;
         public Map<Name, PackageSymbol> visiblePackages;
+        public Collection<ModuleSymbol> readModules;
         public List<Symbol> enclosedPackages = List.nil();
 
         public Completer usesProvidesCompleter = Completer.NULL_COMPLETER;
+        public final Set<ModuleFlags> flags = EnumSet.noneOf(ModuleFlags.class);
 
         /**
          * Create a ModuleSymbol with an associated module-info ClassSymbol.
@@ -994,6 +999,27 @@
 
     }
 
+    public enum ModuleFlags {
+        WEAK(0x0020),
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000);
+
+        // XXX: also in Directive.RequiresFlag, should unify!
+        public static int value(Set<ModuleFlags> s) {
+            int v = 0;
+            for (ModuleFlags f: s)
+                v |= f.value;
+            return v;
+        }
+
+        private ModuleFlags(int value) {
+            this.value = value;
+        }
+
+        public final int value;
+
+    }
+
     /** A class for package symbols
      */
     public static class PackageSymbol extends TypeSymbol
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Tue Sep 06 11:50:40 2016 +0200
@@ -30,6 +30,7 @@
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.lang.model.element.ElementVisitor;
 
@@ -64,6 +65,7 @@
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
+import com.sun.tools.javac.code.Symbol.ModuleFlags;
 import static com.sun.tools.javac.code.TypeTag.*;
 
 /** A class that defines all predefined constants and operators
@@ -451,6 +453,7 @@
             java_base = enterModule(names.java_base);
             //avoid completing java.base during the Symtab initialization
             java_base.completer = Completer.NULL_COMPLETER;
+            java_base.readModules = Collections.emptyList();
             java_base.visiblePackages = Collections.emptyMap();
         } else {
             java_base = noModule;
@@ -630,32 +633,27 @@
         if (pack != null && pack.exists())
             return pack;
 
-        boolean dependsOnUnnamed = msym.requires != null &&
-                                   msym.requires.stream()
-                                                .map(rd -> rd.module)
-                                                .anyMatch(mod -> mod == unnamedModule);
+        Collection<ModuleSymbol> unfilledModules =
+                msym.readModules.stream()
+                                .filter(mod -> mod == unnamedModule || mod.flags.contains(ModuleFlags.WEAK))
+                                .collect(Collectors.toList());
 
-        if (dependsOnUnnamed) {
-            //msyms depends on the unnamed module, for which we generally don't know
+        if (!unfilledModules.isEmpty()) {
+            //msyms depends on an "unfilled" module (unnamed or weak), for which we generally don't know
             //the list of packages it "exports" ahead of time. So try to lookup the package in the
-            //current module, and in the unnamed module and see if it exists in one of them
-            PackageSymbol unnamedPack = getPackage(unnamedModule, flatName);
-
-            if (unnamedPack != null && unnamedPack.exists()) {
-                msym.visiblePackages.put(unnamedPack.fullname, unnamedPack);
-                return unnamedPack;
-            }
-
+            //current module, and in the unfilled modules and see if it exists in any of them
             pack = enterPackage(msym, flatName);
             pack.complete();
             if (pack.exists())
                 return pack;
 
-            unnamedPack = enterPackage(unnamedModule, flatName);
-            unnamedPack.complete();
-            if (unnamedPack.exists()) {
-                msym.visiblePackages.put(unnamedPack.fullname, unnamedPack);
-                return unnamedPack;
+            for (ModuleSymbol unfilled : unfilledModules) {
+                PackageSymbol unfilledPack = enterPackage(unfilled, flatName);
+                unfilledPack.complete();
+                if (unfilledPack.exists()) {
+                    msym.visiblePackages.put(unfilledPack.fullname, unfilledPack);
+                    return unfilledPack;
+                }
             }
 
             return pack;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Tue Sep 06 11:50:40 2016 +0200
@@ -109,6 +109,7 @@
 
 import static com.sun.tools.javac.code.Flags.ABSTRACT;
 import static com.sun.tools.javac.code.Flags.ENUM;
+import com.sun.tools.javac.code.Symbol.ModuleFlags;
 
 /**
  *  TODO: fill in
@@ -602,15 +603,16 @@
         public void visitModuleDef(JCModuleDecl tree) {
             sym = Assert.checkNonNull(tree.sym);
 
+            if (tree.weak) {
+                sym.flags.add(ModuleFlags.WEAK);
+            }
+
             sym.requires = List.nil();
             sym.exports = List.nil();
             tree.directives.forEach(t -> t.accept(this));
             sym.requires = sym.requires.reverse();
             sym.exports = sym.exports.reverse();
             ensureJavaBase();
-            if (tree.weak) {
-                ensureExportsDynamicPrivateDefault();
-            }
         }
 
         @Override
@@ -637,21 +639,15 @@
         public void visitExports(JCExports tree) {
             PackageSymbol packge;
 
-            if (tree.qualid == null) {
-                if (!tree.isDynamicPhase) {
-                    log.error(tree.pos(), Errors.DefaultExportsMustBeDynamic);
-                }
-                // TODO: more validity checking:
-                // must not conflict with other default exports
-                packge = null;
-            } else {
-                Name name = TreeInfo.fullName(tree.qualid);
-                packge = syms.enterPackage(sym, name);
-                attr.setPackageSymbols(tree.qualid, packge);
+            Name name = TreeInfo.fullName(tree.qualid);
+            packge = syms.enterPackage(sym, name);
+            attr.setPackageSymbols(tree.qualid, packge);
+
+            if (sym.flags.contains(ModuleFlags.WEAK)) {
+                log.error(tree.pos(), Errors.NoExportsInWeak);
             }
-
             List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil());
-            for (ExportsDirective d : allExports.computeIfAbsent(packge, p -> List.nil())) {
+            for (ExportsDirective d : exportsForPackage) {
                 checkDuplicateExports(tree, packge, d);
             }
 
@@ -676,9 +672,6 @@
 
             if (toModules == null || !toModules.isEmpty()) {
                 Set<ExportsFlag> flags = EnumSet.noneOf(ExportsFlag.class);
-                if (tree.isDynamicPhase) {
-                    flags.add(ExportsFlag.DYNAMIC_PHASE);
-                }
                 if (tree.isPrivate) {
                     flags.add(ExportsFlag.REFLECTION);
                 }
@@ -703,24 +696,21 @@
                     reportExportConflict(tree, packge);
                 } else {
                     // tree unqualified, directive qualified:
-                    // error if directive (i.e. qualified) does not remove dynamic or add private
-                    if (!(tree.isDynamicPhase && !d.isDynamic()
-                            || !tree.isPrivate && d.isPrivate())) {
+                    // error if directive (i.e. qualified) does not add private
+                    if (tree.isPrivate || !d.isPrivate()) {
                         reportExportConflict(tree, packge);
                     }
                 }
             } else {
                 if (d.modules == null) {
                     // tree qualified, directive unqualified:
-                    // error if tree (i.e. qualified) does not remove dynamic or add private
-                    if (!(d.isDynamic() && !tree.isDynamicPhase
-                            || !d.isPrivate() && tree.isPrivate)) {
+                    // error if tree (i.e. qualified) does not add private
+                    if (d.isPrivate() || !tree.isPrivate) {
                         reportExportConflict(tree, packge);
                     }
                 } else {
                     // both are qualified: error if dynamic and private match
-                    if (tree.isDynamicPhase && d.isDynamic()
-                            && tree.isPrivate && d.isPrivate()) {
+                    if (!(tree.isPrivate ^ d.isPrivate())) {
                         reportExportConflict(tree, packge);
                     }
                 }
@@ -728,11 +718,7 @@
         }
 
         private void reportExportConflict(JCExports tree, PackageSymbol packge) {
-            if (tree.qualid == null) {
-                log.error(tree.pos(), Errors.ConflictingDefaultExports);
-            } else {
-                log.error(tree.qualid.pos(), Errors.ConflictingExports(packge));
-            }
+            log.error(tree.qualid.pos(), Errors.ConflictingExports(packge));
         }
 
         private void checkDuplicateExportsToModule(JCExpression name, ModuleSymbol msym,
@@ -772,18 +758,6 @@
             sym.requires = sym.requires.prepend(d);
         }
 
-        private void ensureExportsDynamicPrivateDefault() {
-            for (ExportsDirective d : sym.exports) {
-                if (d.isDynamic() && d.isPrivate() && d.packge == null) {
-                    return;
-                }
-            }
-            Directive.ExportsDirective d =
-                    new Directive.ExportsDirective(null, null,
-                            EnumSet.of(ExportsFlag.DYNAMIC_PHASE, ExportsFlag.REFLECTION, ExportsFlag.MANDATED));
-            sym.exports = sym.exports.prepend(d);
-        }
-
         private ModuleSymbol lookupModule(JCExpression moduleName) {
             Name name = TreeInfo.fullName(moduleName);
             ModuleSymbol msym = moduleFinder.findModule(name);
@@ -1234,6 +1208,7 @@
     private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) {
         initAddExports();
 
+        msym.readModules = readable;
         msym.visiblePackages = new LinkedHashMap<>();
 
         Map<Name, ModuleSymbol> seen = new HashMap<>();
@@ -1253,11 +1228,6 @@
                                     ModuleSymbol exportsFrom,
                                     Collection<ExportsDirective> exports) {
         for (ExportsDirective d : exports) {
-            // "exports dynamic ..." are not effective at compile-time
-            if (d.flags.contains(ExportsFlag.DYNAMIC_PHASE)) {
-                continue;
-            }
-
             if (d.modules == null || d.modules.contains(msym)) {
                 Name packageName = d.packge.fullname;
                 ModuleSymbol previousModule = seenPackages.get(packageName);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Tue Sep 06 11:50:40 2016 +0200
@@ -828,6 +828,7 @@
             // name as a top-level package.
             if (checkClash &&
                 sym.owner.kind == PCK && sym.owner != env.toplevel.modle.unnamedPackage &&
+                !sym.name.isEmpty() &&
                 syms.packageExists(env.toplevel.modle, sym.fullname)) {
                 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), sym);
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Tue Sep 06 11:50:40 2016 +0200
@@ -583,6 +583,17 @@
         throw badClassFile("bad.module-info.name");
     }
 
+    /** Read module_flags.
+     */
+    Set<ModuleFlags> readModuleFlags(int flags) {
+        Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class);
+        for (ModuleFlags f : ModuleFlags.values()) {
+            if ((flags & f.value) != 0)
+                set.add(f);
+        }
+        return set;
+    }
+
     /** Read exports_flags.
      */
     Set<ExportsFlag> readExportsFlags(int flags) {
@@ -1240,7 +1251,7 @@
                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
                         ListBuffer<Directive> directives = new ListBuffer<>();
 
-                        int module_flags = nextChar();
+                        msym.flags.addAll(readModuleFlags(nextChar()));
 
                         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
                         int nrequires = nextChar();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Tue Sep 06 11:50:40 2016 +0200
@@ -952,7 +952,7 @@
         ModuleSymbol m = (ModuleSymbol) c.owner;
 
         int alenIdx = writeAttr(names.Module);
-        databuf.appendChar(0); // module_flags
+        databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
 
         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
         for (RequiresDirective r: m.requires) {
@@ -968,8 +968,7 @@
         List<ExportsDirective> exports = m.exports;
         databuf.appendChar(exports.size());
         for (ExportsDirective e: exports) {
-            databuf.appendChar(e.packge == null ? 0 :
-                    pool.put(names.fromUtf(externalize(e.packge.flatName()))));
+            databuf.appendChar(pool.put(names.fromUtf(externalize(e.packge.flatName()))));
             databuf.appendChar(ExportsFlag.value(e.flags));
             if (e.modules == null) {
                 databuf.appendChar(0);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Sep 06 11:50:40 2016 +0200
@@ -3262,53 +3262,23 @@
                 defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
             } else if (token.name() == names.exports) {
                 nextToken();
-                boolean isDynamicPhase = false;
                 boolean isPrivate = false;
             loop:
-                while (true) {
-                    switch (token.kind) {
-                        case IDENTIFIER:
-                            if (token.name() == names.dynamic && !isDynamicPhase) {
-                                Token t1 = S.token(1);
-                                if (t1.kind == SEMI || t1.kind == DOT) {
-                                    break loop;
-                                }
-                                isDynamicPhase = true;
-                                break;
-                            } else {
-                                break loop;
-                            }
-                        case PRIVATE:
-                            if (isPrivate) {
-                                error(token.pos, "repeated.modifier");
-                            }
-                            isPrivate = true;
-                            break;
-                        default:
-                            break loop;
+                while (token.kind == PRIVATE) {
+                    if (isPrivate) {
+                        error(token.pos, "repeated.modifier");
                     }
+                    isPrivate = true;
                     nextToken();
                 }
-                JCExpression pkgName;
-                switch (token.kind) {
-                    case DEFAULT:
-                        pkgName = null;
-                        nextToken();
-                        break;
-                    case IDENTIFIER:
-                        pkgName = qualident(false);
-                        break;
-                    default:
-                        reportSyntaxError(token.pos, "expected.identifier.or.default");
-                        pkgName = F.at(token.pos).Erroneous();
-                }
+                JCExpression pkgName = qualident(false);
                 List<JCExpression> moduleNames = null;
                 if (token.kind == IDENTIFIER && token.name() == names.to) {
                     nextToken();
                     moduleNames = qualidentList(false);
                 }
                 accept(SEMI);
-                defs.append(toP(F.at(pos).Exports(pkgName, isDynamicPhase, isPrivate, moduleNames)));
+                defs.append(toP(F.at(pos).Exports(pkgName, isPrivate, moduleNames)));
             } else if (token.name() == names.provides) {
                 nextToken();
                 JCExpression serviceName = qualident(false);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Sep 06 11:50:40 2016 +0200
@@ -1775,9 +1775,6 @@
     reached end of file while parsing
 
 ## The following are related in form, but do not easily fit the above paradigm.
-compiler.err.expected.identifier.or.default=\
-    expected identifier or ''default''
-
 compiler.err.expected.module=\
     ''module'' expected
 
@@ -2731,13 +2728,13 @@
 compiler.err.conflicting.exports=\
     duplicate or conflicting exports: {0}
 
-compiler.err.conflicting.default.exports=\
-    duplicate or conflicting ''exports default''
-
 # 0: symbol
 compiler.err.conflicting.exports.to.module=\
     duplicate or conflicting exports to module: {0}
 
+compiler.err.no.exports.in.weak=\
+    exports not allowed in weak modules
+
 # 0: symbol, 1: symbol
 compiler.err.duplicate.provides=\
     duplicate provides: service {0}, implementation {1}
@@ -2746,9 +2743,6 @@
 compiler.err.duplicate.uses=\
     duplicate uses: {0}
 
-compiler.err.default.exports.must.be.dynamic=\
-    default exports must also specify ''dynamic''
-
 # 0: symbol
 compiler.err.service.implementation.is.abstract=\
     the service implementation is an abstract class: {0}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue Sep 06 11:50:40 2016 +0200
@@ -2685,14 +2685,12 @@
     public static class JCExports extends JCDirective
             implements ExportsTree {
         public JCExpression qualid; // null for default
-        public boolean isDynamicPhase;
         public boolean isPrivate;
         public List<JCExpression> moduleNames;
         public ExportsDirective directive;
 
-        protected JCExports(JCExpression qualId, boolean isDynamicPhase, boolean isPrivate, List<JCExpression> moduleNames) {
+        protected JCExports(JCExpression qualId, boolean isPrivate, List<JCExpression> moduleNames) {
             this.qualid = qualId;
-            this.isDynamicPhase = isDynamicPhase;
             this.isPrivate = isPrivate;
             this.moduleNames = moduleNames;
         }
@@ -2701,11 +2699,6 @@
         public void accept(Visitor v) { v.visitExports(this); }
 
         @Override @DefinedBy(Api.COMPILER_TREE)
-        public boolean isDynamic() {
-            return isDynamicPhase;
-        }
-
-        @Override @DefinedBy(Api.COMPILER_TREE)
         public boolean isPrivate() {
             return isPrivate;
         }
@@ -2993,7 +2986,7 @@
         JCModifiers Modifiers(long flags, List<JCAnnotation> annotations);
         JCErroneous Erroneous(List<? extends JCTree> errs);
         JCModuleDecl ModuleDef(List<JCAnnotation> annotations, boolean weak, JCExpression qualId, List<JCDirective> directives);
-        JCExports Exports(JCExpression qualId, boolean isDynamicPhase, boolean isPrivate, List<JCExpression> moduleNames);
+        JCExports Exports(JCExpression qualId, boolean isPrivate, List<JCExpression> moduleNames);
         JCProvides Provides(JCExpression serviceName, JCExpression implName);
         JCRequires Requires(boolean isTransitive, boolean isStaticPhase, JCExpression qualId);
         JCUses Uses(JCExpression qualId);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Tue Sep 06 11:50:40 2016 +0200
@@ -462,15 +462,8 @@
     public void visitExports(JCExports tree) {
         try {
             print("exports ");
-            if (tree.isDynamicPhase)
-                print("dynamic ");
             if (tree.isPrivate)
                 print("private ");
-            if (tree.qualid == null) {
-                print("default");
-            } else {
-                print(tree.qualid);
-            }
             printExpr(tree.qualid);
             if (tree.moduleNames != null) {
                 print(" to ");
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Tue Sep 06 11:50:40 2016 +0200
@@ -519,7 +519,7 @@
         JCExports t = (JCExports) node;
         JCExpression qualId = copy(t.qualid, p);
         List<JCExpression> moduleNames = copy(t.moduleNames, p);
-        return M.at(t.pos).Exports(qualId, t.isDynamicPhase, t.isPrivate, moduleNames);
+        return M.at(t.pos).Exports(qualId, t.isPrivate, moduleNames);
     }
 
     @Override @DefinedBy(Api.COMPILER_TREE)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Tue Sep 06 11:50:40 2016 +0200
@@ -546,8 +546,8 @@
     }
 
     @Override
-    public JCExports Exports(JCExpression qualId, boolean isDynamicPhase, boolean isPrivate, List<JCExpression> moduleNames) {
-        JCExports tree = new JCExports(qualId, isDynamicPhase, isPrivate, moduleNames);
+    public JCExports Exports(JCExpression qualId, boolean isPrivate, List<JCExpression> moduleNames) {
+        JCExports tree = new JCExports(qualId, isPrivate, moduleNames);
         tree.pos = pos;
         return tree;
     }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Tue Sep 06 11:50:40 2016 +0200
@@ -541,7 +541,7 @@
 
         @Override
         public Void visitModule(Module_attribute attr, ClassOutputStream out) {
-            out.writeShort(0);  // module_flags
+            out.writeShort(attr.module_flags);
 
             out.writeShort(attr.requires.length);
             for (Module_attribute.RequiresEntry e: attr.requires) {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java	Tue Sep 06 11:50:40 2016 +0200
@@ -38,14 +38,14 @@
 public class Module_attribute extends Attribute {
     public static final int ACC_TRANSITIVE      =   0x10;
     public static final int ACC_STATIC_PHASE    =   0x20;
-    public static final int ACC_DYNAMIC_PHASE   =   0x40;
+    public static final int ACC_WEAK            =   0x20;
     public static final int ACC_REFLECTION      =   0x80;
     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);
-        int module_flags = cr.readUnsignedShort();
+        module_flags = cr.readUnsignedShort();
         requires_count = cr.readUnsignedShort();
         requires = new RequiresEntry[requires_count];
         for (int i = 0; i < requires_count; i++)
@@ -65,11 +65,13 @@
     }
 
     public Module_attribute(int name_index,
+            int module_flags,
             RequiresEntry[] requires,
             ExportsEntry[] exports,
             int[] uses,
             ProvidesEntry[] provides) {
         super(name_index, 2);
+        this.module_flags = module_flags;
         requires_count = requires.length;
         this.requires = requires;
         exports_count = exports.length;
@@ -91,6 +93,7 @@
         return visitor.visitModule(this, data);
     }
 
+    public final int module_flags;
     public final int requires_count;
     public final RequiresEntry[] requires;
     public final int exports_count;
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java	Tue Sep 06 11:50:40 2016 +0200
@@ -550,8 +550,6 @@
                 print(" ACC_MANDATED");
             if ((e.exports_flags & Module_attribute.ACC_SYNTHETIC) != 0)
                 print(" ACC_SYNTHETIC");
-            if ((e.exports_flags & Module_attribute.ACC_DYNAMIC_PHASE) != 0)
-                print(" ACC_DYNAMIC_PHASE");
             if ((e.exports_flags & Module_attribute.ACC_REFLECTION) != 0)
                 print(" ACC_PRIVATE_REFLECTION");
             if (e.exports_to_index.length == 0) {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java	Tue Sep 06 11:50:40 2016 +0200
@@ -163,6 +163,10 @@
         writeModifiers(flags.getClassModifiers());
 
         if (classFile.access_flags.is(AccessFlags.ACC_MODULE) && name.endsWith(".module-info")) {
+            Attribute attr = classFile.attributes.get(Attribute.Module);
+            if (attr instanceof Module_attribute && (((Module_attribute) attr).module_flags & Module_attribute.ACC_WEAK) != 0) {
+                print("weak ");
+            }
             print("module ");
             print(name.replace(".module-info", ""));
         } else {
@@ -566,16 +570,10 @@
 
         for (Module_attribute.ExportsEntry entry: m.exports) {
             print("exports");
-            if ((entry.exports_flags & Module_attribute.ACC_DYNAMIC_PHASE) != 0)
-                print(" dynamic");
             if ((entry.exports_flags & Module_attribute.ACC_REFLECTION) != 0)
                 print(" private");
             print(" ");
-            if (entry.exports_index == 0) {
-                print("default");
-            } else {
-                print(getUTF8Value(entry.exports_index).replace('/', '.'));
-            }
+            print(getUTF8Value(entry.exports_index).replace('/', '.'));
             boolean first = true;
             for (int i: entry.exports_to_index) {
                 String mname;
--- a/test/tools/javac/classfiles/attributes/Module/ModuleTest.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/test/tools/javac/classfiles/attributes/Module/ModuleTest.java	Tue Sep 06 11:50:40 2016 +0200
@@ -63,23 +63,13 @@
     }
 
     @Test
-    public void testDynamicExports(Path base) throws Exception {
-        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .exports("pack", ExportFlag.DYNAMIC)
-                .write(base);
-        tb.writeJavaFiles(base, "package pack; public class C extends java.util.ArrayList{ }");
-        compile(base);
-        testModuleAttribute(base, moduleDescriptor);
-    }
-
-    @Test
     public void testSeveralExports(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .exports("pack")
                 .exports("pack2")
-                .exports("pack3", ExportFlag.DYNAMIC)
+                .exports("pack3")
                 .exports("pack4")
-                .exports("pack5", ExportFlag.DYNAMIC)
+                .exports("pack5")
                 .write(base);
         tb.writeJavaFiles(base,
                 "package pack; public class A { }",
@@ -104,7 +94,7 @@
     @Test
     public void testQualifiedDynamicExports(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .exportsTo("pack", "jdk.compiler", ExportFlag.DYNAMIC)
+                .exportsTo("pack", "jdk.compiler")
                 .write(base);
         tb.writeJavaFiles(base, "package pack; public class A { }");
         compile(base);
@@ -117,8 +107,8 @@
                 .exportsTo("pack", "jdk.compiler, jdk.jdeps")
                 .exportsTo("pack2", "jdk.jdeps")
                 .exportsTo("pack3", "jdk.compiler")
-                .exportsTo("pack4", "jdk.compiler, jdk.jdeps", ExportFlag.DYNAMIC)
-                .exportsTo("pack5", "jdk.compiler", ExportFlag.DYNAMIC)
+                .exportsTo("pack4", "jdk.compiler, jdk.jdeps")
+                .exportsTo("pack5", "jdk.compiler")
                 .write(base);
         tb.writeJavaFiles(base,
                 "package pack; public class A {}",
@@ -226,9 +216,9 @@
         Path m1 = base.resolve("m1");
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .exports("pack1")
-                .exports("pack3", ExportFlag.DYNAMIC)
+                .exports("pack3")
                 .exportsTo("packTo1", "m2")
-                .exportsTo("packTo3", "m3", ExportFlag.DYNAMIC)
+                .exportsTo("packTo3", "m3")
                 .requires("jdk.compiler")
                 .requires("m2", RequiresFlag.TRANSITIVE)
                 .requires("m3", RequiresFlag.STATIC)
@@ -241,9 +231,9 @@
                 .requires("m5", RequiresFlag.STATIC)
                 .requires("m6", RequiresFlag.TRANSITIVE)
                 .requires("java.compiler")
-                .exportsTo("packTo4", "java.compiler", ExportFlag.DYNAMIC)
+                .exportsTo("packTo4", "java.compiler")
                 .exportsTo("packTo2", "java.compiler")
-                .exports("pack4", ExportFlag.DYNAMIC)
+                .exports("pack4")
                 .exports("pack2")
                 .write(m1);
         tb.writeJavaFiles(m1, "package pack1; public class C extends java.util.ArrayList{ }",
--- a/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java	Tue Sep 06 11:50:40 2016 +0200
@@ -170,7 +170,6 @@
     }
 
     enum ExportFlag implements Mask {
-        DYNAMIC("dynamic", Module_attribute.ACC_DYNAMIC_PHASE),
         PRIVATE("private", Module_attribute.ACC_REFLECTION);
 
         private final String token;
--- a/test/tools/javac/diags/examples/ConflictingDefaultExports/module-info.java	Mon Sep 05 08:46:13 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.conflicting.default.exports
-
-module ConflictingDefaultExports {
-    exports dynamic default;
-    exports dynamic private default;
-}
--- a/test/tools/javac/diags/examples/DefaultExportsMustBeDynamic/module-info.java	Mon Sep 05 08:46:13 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.default.exports.must.be.dynamic
-
-module m {
-     exports default;
-}
--- a/test/tools/javac/diags/examples/ExpectedIdentifierOrDefault/module-info.java	Mon Sep 05 08:46:13 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.
- */
-
-// key: compiler.err.expected.identifier.or.default
-
-module m {
-    exports *;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/NoExportsInWeak/module-info.java	Tue Sep 06 11:50:40 2016 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.no.exports.in.weak
+
+weak module NoExportsInWeak {
+    exports p;
+}
--- a/test/tools/javac/modules/ModuleInfoTest.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/test/tools/javac/modules/ModuleInfoTest.java	Tue Sep 06 11:50:40 2016 +0200
@@ -34,6 +34,7 @@
  * @run main ModuleInfoTest
  */
 
+import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
@@ -154,37 +155,6 @@
     }
 
     /**
-     * Verify that dynamic exports are reported as missing.
-     */
-    @Test
-    public void testExportsDynamicNotFound(Path base) throws Exception {
-        Path src = base.resolve("src");
-
-        tb.writeJavaFiles(src.resolve("m1"),
-                "module m1 { requires m2; }",
-                "package pack1; public class B { pack.A a; }"
-        );
-        tb.writeJavaFiles(src.resolve("m2"),
-                "module m2 { exports dynamic pack; }",
-                "package pack; public class A { }"
-        );
-
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics", "--module-source-path", src.toString())
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("B.java:1:37: compiler.err.not.def.access.package.cant.access: pack.A, pack"))
-            throw new Exception("expected output not found");
-    }
-
-    /**
      * Verify that a simple loop is detected.
      */
     @Test
@@ -311,97 +281,103 @@
     }
 
     /**
-     * Verify that duplicate exported packages are detected.
+     * Verify that duplicate exported packages are detected correctly.
      */
     @Test
     public void testConflictingExports_packages(Path base) throws Exception {
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports q;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports p;",
+                                          "module-info.java:1:32: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports private p;",
+                                          "module-info.java:1:40: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports p to m2;",
+                                          "module-info.java:1:32: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports private p to m2;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports private p; exports p;",
+                                          "module-info.java:1:40: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports private p; exports private p;",
+                                          "module-info.java:1:48: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports private p; exports p to m2;",
+                                          "module-info.java:1:40: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports private p; exports private p to m2;",
+                                          "module-info.java:1:48: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports p;",
+                                          "module-info.java:1:38: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports private p;",
+                                          "module-info.java:1:46: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports p to m2;",
+                                          "module-info.java:1:43: compiler.err.conflicting.exports.to.module: m2");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports private p to m2;",
+                                          "module-info.java:1:51: compiler.err.conflicting.exports.to.module: m2");
+        verifyConflictingExports_packages(base,
+                                          "exports private p to m2; exports p;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports private p to m2; exports private p;",
+                                          "module-info.java:1:54: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports private p to m2; exports p to m2;",
+                                          "module-info.java:1:51: compiler.err.conflicting.exports.to.module: m2");
+        verifyConflictingExports_packages(base,
+                                          "exports private p to m2; exports private p to m2;",
+                                          "module-info.java:1:54: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports p to m3;",
+                                          "module-info.java:1:38: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports private p to m3;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports private p to m2; exports p to m3;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports private p to m2; exports private p to m3;",
+                                          "module-info.java:1:54: compiler.err.conflicting.exports: p");
+    }
+
+    private void verifyConflictingExports_packages(Path base, String code, String expected) throws Exception {
+        Files.createDirectories(base);
+        tb.cleanDirectory(base);
+
         Path src = base.resolve("src");
-        tb.writeJavaFiles(src, "module m1 { exports p; exports p; }");
+        tb.writeJavaFiles(src.resolve("m1"),
+                          "module m1 { " + code + " }",
+                          "package p; public class P {}",
+                          "package q; public class Q {}");
+        tb.writeJavaFiles(src.resolve("m2"),
+                          "module m2 { requires m1; }");
+        tb.writeJavaFiles(src.resolve("m3"),
+                          "module m3 { requires m1; }");
 
         Path classes = base.resolve("classes");
         Files.createDirectories(classes);
 
         String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics")
+                .options("-XDrawDiagnostics",
+                         "--module-source-path", src.toString())
                 .outdir(classes)
                 .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
+                .run(expected != null ? Task.Expect.FAIL : Task.Expect.SUCCESS)
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
 
-        if (!log.contains("module-info.java:1:32: compiler.err.conflicting.exports: p"))
-            throw new Exception("expected output not found");
-    }
-
-    /**
-     * Verify that duplicate exported packages are detected.
-     */
-    @Test
-    public void testConflictingDynamicExports_packages(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src, "module m1 { exports p; exports dynamic p; }");
-
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics")
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("module-info.java:1:40: compiler.err.conflicting.exports: p"))
-            throw new Exception("expected output not found");
-    }
-
-    /**
-     * Verify that duplicate exported packages are detected.
-     */
-    @Test
-    public void testConflictingExports_packages2(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports p to m2; }");
-        tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
-
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics", "--module-source-path", src.toString())
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("module-info.java:1:32: compiler.err.conflicting.exports: p"))
-            throw new Exception("expected output not found");
-    }
-
-    /**
-     * Verify that duplicate exported packages are detected.
-     */
-    @Test
-    public void testConflictingDynamicExports_packages2(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports dynamic p to m2; }");
-        tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
-
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics", "--module-source-path", src.toString())
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("module-info.java:1:40: compiler.err.conflicting.exports: p"))
-            throw new Exception("expected output not found");
+        if (expected != null && !log.contains(expected))
+            throw new Exception("expected output not found, actual output: " + log);
     }
 
     /**
@@ -431,34 +407,6 @@
     }
 
     /**
-     * Verify that duplicate exported packages are detected.
-     */
-    @Test
-    public void testConflictingDynamicExports_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.writeJavaFiles(src_m2,
-                "module m2 { exports dynamic p to m1, m1; }",
-                "package p; public class C { }");
-
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics", "--module-source-path", src.toString())
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("module-info.java:1:38: compiler.err.conflicting.exports.to.module: m1"))
-            throw new Exception("expected output not found");
-    }
-
-    /**
      * Verify that annotations are not permitted at
      * any of the module names or the package names.
      */
@@ -496,13 +444,11 @@
                     .getOutput(Task.OutputKind.DIRECT);
 
             String expect_prefix = "(?s)^module\\-info\\.java:\\d+:\\d+: ";
-            String expect_message = moduleInfo.contains("exports @")
-                ? "compiler\\.err\\.expected\\.identifier\\.or\\.default"
-                : "compiler\\.err\\.expected: token\\.identifier";
+            String expect_message = "compiler\\.err\\.expected: token\\.identifier";
             String expect_suffix = ".*";
             String expect = expect_prefix + expect_message + expect_suffix;
             if (!log.matches(expect))
-                throw new Exception("expected output not found");
+                throw new Exception("expected output not found for: " + moduleInfo + "; actual: " + log);
         }
     }
 }
--- a/test/tools/javac/modules/PackageConflictTest.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/test/tools/javac/modules/PackageConflictTest.java	Tue Sep 06 11:50:40 2016 +0200
@@ -124,31 +124,6 @@
     }
 
     @Test
-    public void testConflictInDependenciesDynamicExport(Path base) throws Exception {
-        Path m1 = base.resolve("m1");
-        Path m2 = base.resolve("m2");
-        Path m3 = base.resolve("m3");
-        tb.writeJavaFiles(m1,
-                "module m1 { exports test; }",
-                "package test; public class A { }");
-        tb.writeJavaFiles(m2,
-                "module m2 { exports dynamic test; }",
-                "package test; public class B { }");
-        tb.writeJavaFiles(m3,
-                "module m3 { requires m1; requires m2; }",
-                "package impl; public class Impl { }");
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        new JavacTask(tb)
-                .options("-XDrawDiagnostics", "--module-source-path", base.toString())
-                .outdir(classes)
-                .files(findJavaFiles(base))
-                .run(Task.Expect.SUCCESS)
-                .writeAll();
-    }
-
-    @Test
     public void testSimple2(Path base) throws Exception {
         Path modSrc = base.resolve("modSrc");
         Path modules = base.resolve("modules");
--- a/test/tools/javac/modules/ReportNonExistentPackageTest.java	Mon Sep 05 08:46:13 2016 +0100
+++ b/test/tools/javac/modules/ReportNonExistentPackageTest.java	Tue Sep 06 11:50:40 2016 +0200
@@ -64,24 +64,6 @@
     }
 
     @Test
-    public void testExportDynamicUnknownPackage(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src, "module m { exports dynamic p1; }");
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics")
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-        if (!log.contains("module-info.java:1:28: compiler.err.package.empty.or.not.found: p1"))
-            throw new Exception("expected output not found");
-    }
-
-    @Test
     public void testExportEmptyPackage(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/WeakModulesTest.java	Tue Sep 06 11:50:40 2016 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for multi-module mode compilation
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
+ * @run main WeakModulesTest
+ */
+
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+import toolbox.JavacTask;
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.Task.OutputKind;
+
+public class WeakModulesTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new WeakModulesTest().runTests();
+    }
+
+    @Test
+    public void testWeakModule(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "weak module m1 { }",
+                          "package api1; public class Api1 {}",
+                          "package api2; public class Api2 {}");
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        tb.createDirectories(m1Classes);
+
+        String log = new JavacTask(tb)
+                .outdir(m1Classes)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+
+        String decompiled = new JavapTask(tb)
+                .options("--system", "none", "-bootclasspath", "")
+                .classpath(m1Classes.toString())
+                .classes("module-info")
+                .run()
+                .writeAll()
+                .getOutput(OutputKind.DIRECT)
+                .replace(System.getProperty("line.separator"), "\n");
+
+        String expected = "weak module m1 {\n" +
+                          "  requires java.base;\n" +
+                          "}";
+
+        if (!decompiled.contains(expected)) {
+            throw new Exception("expected output not found: " + decompiled);
+        }
+
+        //compiling against a weak module read from binary:
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m2,
+                          "module m2 { requires m1; }",
+                          "package test; public class Test { api1.Api1 a1; api2.Api2 a2; }");
+        Path m2Classes = classes.resolve("m2");
+        tb.createDirectories(m2Classes);
+
+        String log2 = new JavacTask(tb)
+                .options("--module-path", m1Classes.toString())
+                .outdir(m2Classes)
+                .files(findJavaFiles(m2))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log2.isEmpty())
+            throw new Exception("expected output not found: " + log2);
+    }
+
+    @Test
+    public void testWeakModuleOnModuleSourcePath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "weak module m1 { }",
+                          "package api1; public class Api1 {}",
+                          "package api2; public class Api2 {}");
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m2,
+                          "module m2 { requires m1; }",
+                          "package test; public class Test { api1.Api1 a1; api2.Api2 a2; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("--module-source-path", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    public void testNoExportsInWeakModules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "weak module m1 { exports api1; }",
+                          "package api1; public class Api1 {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:18: compiler.err.no.exports.in.weak",
+                "1 error"
+        );
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+}