1 /* 2 * Copyright (c) 2015, 2016, 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 23 * questions. 24 */ 25 26 package jdk.internal.module; 27 28 import java.lang.module.Configuration; 29 import java.lang.module.ModuleDescriptor; 30 import java.lang.module.ModuleFinder; 31 import java.lang.module.ModuleReference; 32 import java.lang.module.ResolvedModule; 33 import java.net.URI; 34 import java.security.AccessController; 35 import java.security.PrivilegedAction; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Set; 39 import java.util.function.Function; 40 import java.util.stream.Collectors; 41 42 import jdk.internal.loader.BootLoader; 43 import jdk.internal.loader.BuiltinClassLoader; 44 import jdk.internal.loader.ClassLoaders; 45 import jdk.internal.misc.JavaLangAccess; 46 import jdk.internal.misc.SharedSecrets; 47 48 /** 49 * A helper class for creating and updating modules. This class is intended to 50 * support command-line options, tests, and the instrumentation API. It is also 51 * used by the VM to load modules or add read edges when agents are instrumenting 52 * code that need to link to supporting classes. 53 * 54 * The parameters that are package names in this API are the fully-qualified 55 * names of the packages as defined in section 6.5.3 of <cite>The Java™ 56 * Language Specification </cite>, for example, {@code "java.lang"}. 57 */ 58 59 public class Modules { 60 private Modules() { } 61 62 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); 63 64 /** 65 * Creates a new Module. The module has the given ModuleDescriptor and 66 * is defined to the given class loader. 67 * 68 * The resulting Module is in a larval state in that it does not not read 69 * any other module and does not have any exports. 70 * 71 * The URI is for information purposes only. 72 */ 73 public static Module defineModule(ClassLoader loader, 74 ModuleDescriptor descriptor, 75 URI uri) 76 { 77 return JLA.defineModule(loader, descriptor, uri); 78 } 79 80 /** 81 * Updates m1 to read m2. 82 * Same as m1.addReads(m2) but without a caller check. 83 */ 84 public static void addReads(Module m1, Module m2) { 85 JLA.addReads(m1, m2); 86 } 87 88 /** 89 * Update module m to read all unnamed modules. 90 */ 91 public static void addReadsAllUnnamed(Module m) { 92 JLA.addReadsAllUnnamed(m); 93 } 94 95 /** 96 * Updates module m1 to export a package to module m2. 97 * Same as m1.addExports(pn, m2) but without a caller check 98 */ 99 public static void addExports(Module m1, String pn, Module m2) { 100 JLA.addExports(m1, pn, m2); 101 } 102 103 /** 104 * Updates module m to export a package to all unnamed modules. 105 */ 106 public static void addExportsToAllUnnamed(Module m, String pn) { 107 JLA.addExportsToAllUnnamed(m, pn); 108 } 109 110 /** 111 * Updates module m1 to open a package to module m2. 112 * Same as m1.addOpens(pn, m2) but without a caller check. 113 */ 114 public static void addOpens(Module m1, String pn, Module m2) { 115 JLA.addOpens(m1, pn, m2); 116 } 117 118 /** 119 * Updates module m to open a package to all unnamed modules. 120 */ 121 public static void addOpensToAllUnnamed(Module m, String pn) { 122 JLA.addOpensToAllUnnamed(m, pn); 123 } 124 125 /** 126 * Updates module m to use a service. 127 * Same as m2.addUses(service) but without a caller check. 128 */ 129 public static void addUses(Module m, Class<?> service) { 130 JLA.addUses(m, service); 131 } 132 133 /** 134 * Updates module m to provide a service 135 */ 136 public static void addProvides(Module m, Class<?> service, Class<?> impl) { 137 ModuleLayer layer = m.getLayer(); 138 139 PrivilegedAction<ClassLoader> pa = m::getClassLoader; 140 ClassLoader loader = AccessController.doPrivileged(pa); 141 142 ClassLoader platformClassLoader = ClassLoaders.platformClassLoader(); 143 if (layer == null || loader == null || loader == platformClassLoader) { 144 // update ClassLoader catalog 145 ServicesCatalog catalog; 146 if (loader == null) { 147 catalog = BootLoader.getServicesCatalog(); 148 } else { 149 catalog = ServicesCatalog.getServicesCatalog(loader); 150 } 151 catalog.addProvider(m, service, impl); 152 } 153 154 if (layer != null) { 155 // update Layer catalog 156 JLA.getServicesCatalog(layer).addProvider(m, service, impl); 157 } 158 } 159 160 /** 161 * Called by the VM when code in the given Module has been transformed by 162 * an agent and so may have been instrumented to call into supporting 163 * classes on the boot class path or application class path. 164 */ 165 public static void transformedByAgent(Module m) { 166 addReads(m, BootLoader.getUnnamedModule()); 167 addReads(m, ClassLoaders.appClassLoader().getUnnamedModule()); 168 } 169 170 /** 171 * Called by the VM to load a system module, typically "java.instrument" or 172 * "jdk.management.agent". If the module is not loaded then it is resolved 173 * and loaded (along with any dependences that weren't previously loaded) 174 * into a child layer. 175 */ 176 public static synchronized Module loadModule(String name) { 177 ModuleLayer top = topLayer; 178 if (top == null) 179 top = ModuleLayer.boot(); 180 181 Module module = top.findModule(name).orElse(null); 182 if (module != null) { 183 // module already loaded 184 return module; 185 } 186 187 // resolve the module with the top-most layer as the parent 188 ModuleFinder empty = ModuleFinder.of(); 189 ModuleFinder finder = ModuleBootstrap.unlimitedFinder(); 190 Set<String> roots = Set.of(name); 191 Configuration cf = top.configuration().resolveAndBind(empty, finder, roots); 192 193 // create the child layer 194 Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf); 195 ModuleLayer newLayer = top.defineModules(cf, clf); 196 197 // add qualified exports/opens to give access to modules in child layer 198 Map<String, Module> map = newLayer.modules().stream() 199 .collect(Collectors.toMap(Module::getName, 200 Function.identity())); 201 ModuleLayer layer = top; 202 while (layer != null) { 203 for (Module m : layer.modules()) { 204 // qualified exports 205 m.getDescriptor().exports().stream() 206 .filter(ModuleDescriptor.Exports::isQualified) 207 .forEach(e -> e.targets().forEach(target -> { 208 Module other = map.get(target); 209 if (other != null) { 210 addExports(m, e.source(), other); 211 }})); 212 213 // qualified opens 214 m.getDescriptor().opens().stream() 215 .filter(ModuleDescriptor.Opens::isQualified) 216 .forEach(o -> o.targets().forEach(target -> { 217 Module other = map.get(target); 218 if (other != null) { 219 addOpens(m, o.source(), other); 220 }})); 221 } 222 223 List<ModuleLayer> parents = layer.parents(); 224 assert parents.size() <= 1; 225 layer = parents.isEmpty() ? null : parents.get(0); 226 } 227 228 // update security manager before making types visible 229 JLA.addNonExportedPackages(newLayer); 230 231 // update the built-in class loaders to make the types visible 232 for (ResolvedModule resolvedModule : cf.modules()) { 233 ModuleReference mref = resolvedModule.reference(); 234 String mn = mref.descriptor().name(); 235 ClassLoader cl = clf.apply(mn); 236 if (cl == null) { 237 BootLoader.loadModule(mref); 238 } else { 239 ((BuiltinClassLoader) cl).loadModule(mref); 240 } 241 } 242 243 // new top layer 244 topLayer = newLayer; 245 246 // return module 247 return newLayer.findModule(name) 248 .orElseThrow(() -> new InternalError("module not loaded")); 249 250 } 251 252 // the top-most system layer 253 private static ModuleLayer topLayer; 254 255 }