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 }
|