< prev index next >

src/java.base/share/classes/java/lang/Module.java

Print this page
rev 57859 : 8237484: Improve module system bootstrap
Reviewed-by: alanb
   1 /*
   2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 115      * Creates a new named Module. The resulting Module will be defined to the
 116      * VM but will not read any other modules, will not have any exports setup
 117      * and will not be registered in the service catalog.
 118      */
 119     Module(ModuleLayer layer,
 120            ClassLoader loader,
 121            ModuleDescriptor descriptor,
 122            URI uri)
 123     {
 124         this.layer = layer;
 125         this.name = descriptor.name();
 126         this.loader = loader;
 127         this.descriptor = descriptor;
 128 
 129         // define module to VM
 130 
 131         boolean isOpen = descriptor.isOpen() || descriptor.isAutomatic();
 132         Version version = descriptor.version().orElse(null);
 133         String vs = Objects.toString(version, null);
 134         String loc = Objects.toString(uri, null);
 135         String[] packages = descriptor.packages().toArray(new String[0]);
 136         defineModule0(this, isOpen, vs, loc, packages);
 137     }
 138 
 139 
 140     /**
 141      * Create the unnamed Module for the given ClassLoader.
 142      *
 143      * @see ClassLoader#getUnnamedModule
 144      */
 145     Module(ClassLoader loader) {
 146         this.layer = null;
 147         this.name = null;
 148         this.loader = loader;
 149         this.descriptor = null;
 150     }
 151 
 152 
 153     /**
 154      * Creates a named module but without defining the module to the VM.
 155      *


1055 
1056     // -- creating Module objects --
1057 
1058     /**
1059      * Defines all module in a configuration to the runtime.
1060      *
1061      * @return a map of module name to runtime {@code Module}
1062      *
1063      * @throws IllegalArgumentException
1064      *         If the function maps a module to the null or platform class loader
1065      * @throws IllegalStateException
1066      *         If the module cannot be defined to the VM or its packages overlap
1067      *         with another module mapped to the same class loader
1068      */
1069     static Map<String, Module> defineModules(Configuration cf,
1070                                              Function<String, ClassLoader> clf,
1071                                              ModuleLayer layer)
1072     {
1073         boolean isBootLayer = (ModuleLayer.boot() == null);
1074 
1075         int cap = (int)(cf.modules().size() / 0.75f + 1.0f);

1076         Map<String, Module> nameToModule = new HashMap<>(cap);
1077         Map<String, ClassLoader> nameToLoader = new HashMap<>(cap);
1078 
1079         Set<ClassLoader> loaders = new HashSet<>();










1080         boolean hasPlatformModules = false;
1081 
1082         // map each module to a class loader
1083         for (ResolvedModule resolvedModule : cf.modules()) {
1084             String name = resolvedModule.name();


1085             ClassLoader loader = clf.apply(name);
1086             nameToLoader.put(name, loader);
1087             if (loader == null || loader == ClassLoaders.platformClassLoader()) {
1088                 if (!(clf instanceof ModuleLoaderMap.Mapper)) {
1089                     throw new IllegalArgumentException("loader can't be 'null'"
1090                             + " or the platform class loader");
1091                 }
1092                 hasPlatformModules = true;
1093             } else {
1094                 loaders.add(loader);
1095             }


1096         }
1097 
1098         // define each module in the configuration to the VM
1099         for (ResolvedModule resolvedModule : cf.modules()) {
1100             ModuleReference mref = resolvedModule.reference();
1101             ModuleDescriptor descriptor = mref.descriptor();
1102             String name = descriptor.name();
1103             ClassLoader loader = nameToLoader.get(name);
1104             Module m;
1105             if (loader == null && name.equals("java.base")) {
1106                 // java.base is already defined to the VM
1107                 m = Object.class.getModule();
1108             } else {
1109                 URI uri = mref.location().orElse(null);
1110                 m = new Module(layer, loader, descriptor, uri);
1111             }
1112             nameToModule.put(name, m);

1113         }
1114 
1115         // setup readability and exports/opens
1116         for (ResolvedModule resolvedModule : cf.modules()) {

1117             ModuleReference mref = resolvedModule.reference();
1118             ModuleDescriptor descriptor = mref.descriptor();
1119 
1120             String mn = descriptor.name();
1121             Module m = nameToModule.get(mn);
1122             assert m != null;
1123 
1124             // reads
1125             Set<Module> reads = new HashSet<>();
1126 
1127             // name -> source Module when in parent layer
1128             Map<String, Module> nameToSource = Map.of();
1129 
1130             for (ResolvedModule other : resolvedModule.reads()) {
1131                 Module m2 = null;
1132                 if (other.configuration() == cf) {
1133                     // this configuration
1134                     m2 = nameToModule.get(other.name());
1135                     assert m2 != null;
1136                 } else {
1137                     // parent layer
1138                     for (ModuleLayer parent: layer.parents()) {
1139                         m2 = findModule(parent, other);
1140                         if (m2 != null)
1141                             break;
1142                     }


1154 
1155             // automatic modules read all unnamed modules
1156             if (descriptor.isAutomatic()) {
1157                 m.implAddReads(ALL_UNNAMED_MODULE, true);
1158             }
1159 
1160             // exports and opens, skipped for open and automatic
1161             if (!descriptor.isOpen() && !descriptor.isAutomatic()) {
1162                 if (isBootLayer && descriptor.opens().isEmpty()) {
1163                     // no open packages, no qualified exports to modules in parent layers
1164                     initExports(m, nameToModule);
1165                 } else {
1166                     initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
1167                 }
1168             }
1169         }
1170 
1171         // if there are modules defined to the boot or platform class loaders
1172         // then register the modules in the class loader's services catalog
1173         if (hasPlatformModules) {
1174             ClassLoader pcl = ClassLoaders.platformClassLoader();
1175             ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
1176             ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl);
1177             for (ResolvedModule resolvedModule : cf.modules()) {

1178                 ModuleReference mref = resolvedModule.reference();
1179                 ModuleDescriptor descriptor = mref.descriptor();
1180                 if (!descriptor.provides().isEmpty()) {
1181                     String name = descriptor.name();
1182                     Module m = nameToModule.get(name);
1183                     ClassLoader loader = nameToLoader.get(name);
1184                     if (loader == null) {
1185                         bootCatalog.register(m);
1186                     } else if (loader == pcl) {
1187                         pclCatalog.register(m);
1188                     }
1189                 }
1190             }
1191         }
1192 
1193         // record that there is a layer with modules defined to the class loader
1194         for (ClassLoader loader : loaders) {
1195             layer.bindToLoader(loader);
1196         }
1197 
1198         return nameToModule;
1199     }
1200 
1201     /**
1202      * Find the runtime Module corresponding to the given ResolvedModule
1203      * in the given parent layer (or its parents).
1204      */
1205     private static Module findModule(ModuleLayer parent,
1206                                      ResolvedModule resolvedModule) {
1207         Configuration cf = resolvedModule.configuration();
1208         String dn = resolvedModule.name();
1209         return parent.layers()
1210                 .filter(l -> l.configuration() == cf)
1211                 .findAny()
1212                 .map(layer -> {
1213                     Optional<Module> om = layer.findModule(dn);
1214                     assert om.isPresent() : dn + " not found in layer";


1603             return "unnamed module @" + id;
1604         }
1605     }
1606 
1607     /**
1608      * Returns the module that a given caller class is a member of. Returns
1609      * {@code null} if the caller is {@code null}.
1610      */
1611     private Module getCallerModule(Class<?> caller) {
1612         return (caller != null) ? caller.getModule() : null;
1613     }
1614 
1615 
1616     // -- native methods --
1617 
1618     // JVM_DefineModule
1619     private static native void defineModule0(Module module,
1620                                              boolean isOpen,
1621                                              String version,
1622                                              String location,
1623                                              String[] pns);
1624 
1625     // JVM_AddReadsModule
1626     private static native void addReads0(Module from, Module to);
1627 
1628     // JVM_AddModuleExports
1629     private static native void addExports0(Module from, String pn, Module to);
1630 
1631     // JVM_AddModuleExportsToAll
1632     private static native void addExportsToAll0(Module from, String pn);
1633 
1634     // JVM_AddModuleExportsToAllUnnamed
1635     private static native void addExportsToAllUnnamed0(Module from, String pn);
1636 }
   1 /*
   2  * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 115      * Creates a new named Module. The resulting Module will be defined to the
 116      * VM but will not read any other modules, will not have any exports setup
 117      * and will not be registered in the service catalog.
 118      */
 119     Module(ModuleLayer layer,
 120            ClassLoader loader,
 121            ModuleDescriptor descriptor,
 122            URI uri)
 123     {
 124         this.layer = layer;
 125         this.name = descriptor.name();
 126         this.loader = loader;
 127         this.descriptor = descriptor;
 128 
 129         // define module to VM
 130 
 131         boolean isOpen = descriptor.isOpen() || descriptor.isAutomatic();
 132         Version version = descriptor.version().orElse(null);
 133         String vs = Objects.toString(version, null);
 134         String loc = Objects.toString(uri, null);
 135         Object[] packages = descriptor.packages().toArray();
 136         defineModule0(this, isOpen, vs, loc, packages);
 137     }
 138 
 139 
 140     /**
 141      * Create the unnamed Module for the given ClassLoader.
 142      *
 143      * @see ClassLoader#getUnnamedModule
 144      */
 145     Module(ClassLoader loader) {
 146         this.layer = null;
 147         this.name = null;
 148         this.loader = loader;
 149         this.descriptor = null;
 150     }
 151 
 152 
 153     /**
 154      * Creates a named module but without defining the module to the VM.
 155      *


1055 
1056     // -- creating Module objects --
1057 
1058     /**
1059      * Defines all module in a configuration to the runtime.
1060      *
1061      * @return a map of module name to runtime {@code Module}
1062      *
1063      * @throws IllegalArgumentException
1064      *         If the function maps a module to the null or platform class loader
1065      * @throws IllegalStateException
1066      *         If the module cannot be defined to the VM or its packages overlap
1067      *         with another module mapped to the same class loader
1068      */
1069     static Map<String, Module> defineModules(Configuration cf,
1070                                              Function<String, ClassLoader> clf,
1071                                              ModuleLayer layer)
1072     {
1073         boolean isBootLayer = (ModuleLayer.boot() == null);
1074 
1075         int numModules = cf.modules().size();
1076         int cap = (int)(numModules / 0.75f + 1.0f);
1077         Map<String, Module> nameToModule = new HashMap<>(cap);

1078 
1079         // to avoid repeated lookups and reduce iteration overhead, we create
1080         // arrays holding correlated information about each module.
1081         ResolvedModule[] resolvedModules = new ResolvedModule[numModules];
1082         Module[] modules = new Module[numModules];
1083         ClassLoader[] classLoaders = new ClassLoader[numModules];
1084 
1085         resolvedModules = cf.modules().toArray(resolvedModules);
1086 
1087         // record that we want to bind the layer to non-boot and non-platform
1088         // module loaders as a final step
1089         HashSet<ClassLoader> toBindLoaders = new HashSet<>(4);
1090         boolean hasPlatformModules = false;
1091 
1092         // map each module to a class loader
1093         ClassLoader pcl = ClassLoaders.platformClassLoader();
1094 
1095         for (int index = 0; index < numModules; index++) {
1096             String name = resolvedModules[index].name();
1097             ClassLoader loader = clf.apply(name);
1098 
1099             if (loader == null || loader == pcl) {
1100                 if (!(clf instanceof ModuleLoaderMap.Mapper)) {
1101                     throw new IllegalArgumentException("loader can't be 'null'"
1102                             + " or the platform class loader");
1103                 }
1104                 hasPlatformModules = true;
1105             } else {
1106                 toBindLoaders.add(loader);
1107             }
1108 
1109             classLoaders[index] = loader;
1110         }
1111 
1112         // define each module in the configuration to the VM
1113         for (int index = 0; index < numModules; index++) {
1114             ModuleReference mref = resolvedModules[index].reference();
1115             ModuleDescriptor descriptor = mref.descriptor();
1116             String name = descriptor.name();
1117             ClassLoader loader = classLoaders[index];
1118             Module m;
1119             if (loader == null && name.equals("java.base")) {
1120                 // java.base is already defined to the VM
1121                 m = Object.class.getModule();
1122             } else {
1123                 URI uri = mref.location().orElse(null);
1124                 m = new Module(layer, loader, descriptor, uri);
1125             }
1126             nameToModule.put(name, m);
1127             modules[index] = m;
1128         }
1129 
1130         // setup readability and exports/opens
1131         for (int index = 0; index < numModules; index++) {
1132             ResolvedModule resolvedModule = resolvedModules[index];
1133             ModuleReference mref = resolvedModule.reference();
1134             ModuleDescriptor descriptor = mref.descriptor();
1135             Module m = modules[index];



1136 
1137             // reads
1138             Set<Module> reads = new HashSet<>();
1139 
1140             // name -> source Module when in parent layer
1141             Map<String, Module> nameToSource = Map.of();
1142 
1143             for (ResolvedModule other : resolvedModule.reads()) {
1144                 Module m2 = null;
1145                 if (other.configuration() == cf) {
1146                     // this configuration
1147                     m2 = nameToModule.get(other.name());
1148                     assert m2 != null;
1149                 } else {
1150                     // parent layer
1151                     for (ModuleLayer parent: layer.parents()) {
1152                         m2 = findModule(parent, other);
1153                         if (m2 != null)
1154                             break;
1155                     }


1167 
1168             // automatic modules read all unnamed modules
1169             if (descriptor.isAutomatic()) {
1170                 m.implAddReads(ALL_UNNAMED_MODULE, true);
1171             }
1172 
1173             // exports and opens, skipped for open and automatic
1174             if (!descriptor.isOpen() && !descriptor.isAutomatic()) {
1175                 if (isBootLayer && descriptor.opens().isEmpty()) {
1176                     // no open packages, no qualified exports to modules in parent layers
1177                     initExports(m, nameToModule);
1178                 } else {
1179                     initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
1180                 }
1181             }
1182         }
1183 
1184         // if there are modules defined to the boot or platform class loaders
1185         // then register the modules in the class loader's services catalog
1186         if (hasPlatformModules) {

1187             ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
1188             ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl);
1189             for (int index = 0; index < numModules; index++) {
1190                 ResolvedModule resolvedModule = resolvedModules[index];
1191                 ModuleReference mref = resolvedModule.reference();
1192                 ModuleDescriptor descriptor = mref.descriptor();
1193                 if (!descriptor.provides().isEmpty()) {
1194                     Module m = modules[index];
1195                     ClassLoader loader = classLoaders[index];

1196                     if (loader == null) {
1197                         bootCatalog.register(m);
1198                     } else if (loader == pcl) {
1199                         pclCatalog.register(m);
1200                     }
1201                 }
1202             }
1203         }
1204 
1205         // record that there is a layer with modules defined to the class loader
1206         for (ClassLoader loader : toBindLoaders) {
1207             layer.bindToLoader(loader);
1208         }
1209 
1210         return nameToModule;
1211     }
1212 
1213     /**
1214      * Find the runtime Module corresponding to the given ResolvedModule
1215      * in the given parent layer (or its parents).
1216      */
1217     private static Module findModule(ModuleLayer parent,
1218                                      ResolvedModule resolvedModule) {
1219         Configuration cf = resolvedModule.configuration();
1220         String dn = resolvedModule.name();
1221         return parent.layers()
1222                 .filter(l -> l.configuration() == cf)
1223                 .findAny()
1224                 .map(layer -> {
1225                     Optional<Module> om = layer.findModule(dn);
1226                     assert om.isPresent() : dn + " not found in layer";


1615             return "unnamed module @" + id;
1616         }
1617     }
1618 
1619     /**
1620      * Returns the module that a given caller class is a member of. Returns
1621      * {@code null} if the caller is {@code null}.
1622      */
1623     private Module getCallerModule(Class<?> caller) {
1624         return (caller != null) ? caller.getModule() : null;
1625     }
1626 
1627 
1628     // -- native methods --
1629 
1630     // JVM_DefineModule
1631     private static native void defineModule0(Module module,
1632                                              boolean isOpen,
1633                                              String version,
1634                                              String location,
1635                                              Object[] pns);
1636 
1637     // JVM_AddReadsModule
1638     private static native void addReads0(Module from, Module to);
1639 
1640     // JVM_AddModuleExports
1641     private static native void addExports0(Module from, String pn, Module to);
1642 
1643     // JVM_AddModuleExportsToAll
1644     private static native void addExportsToAll0(Module from, String pn);
1645 
1646     // JVM_AddModuleExportsToAllUnnamed
1647     private static native void addExportsToAllUnnamed0(Module from, String pn);
1648 }
< prev index next >