1 /* 2 * Copyright (c) 2015, 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 23 * questions. 24 */ 25 26 package jdk.internal.loader; 27 28 import java.io.IOException; 29 import java.net.URL; 30 import java.nio.file.InvalidPathException; 31 import java.nio.file.Path; 32 import java.security.CodeSource; 33 import java.security.PermissionCollection; 34 import java.util.jar.Manifest; 35 36 import jdk.internal.misc.JavaLangAccess; 37 import jdk.internal.misc.SharedSecrets; 38 import jdk.internal.misc.VM; 39 40 /** 41 * Creates and provides access to the built-in platform and application class 42 * loaders. It also creates the class loader that is used to locate resources 43 * in modules defined to the boot class loader. 44 */ 45 46 public class ClassLoaders { 47 48 private ClassLoaders() { } 49 50 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); 51 52 // the built-in class loaders 53 private static final BootClassLoader BOOT_LOADER; 54 private static final PlatformClassLoader PLATFORM_LOADER; 55 private static final AppClassLoader APP_LOADER; 56 57 // Creates the built-in class loaders. 58 static { 59 // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute 60 String append = VM.getSavedProperty("jdk.boot.class.path.append"); 61 BOOT_LOADER = 62 new BootClassLoader((append != null && !append.isEmpty()) 63 ? new URLClassPath(append, true) 64 : null); 65 PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER); 66 67 // A class path is required when no initial module is specified. 68 // In this case the class path defaults to "", meaning the current 69 // working directory. When an initial module is specified, on the 70 // contrary, we drop this historic interpretation of the empty 71 // string and instead treat it as unspecified. 72 String cp = System.getProperty("java.class.path"); 73 if (cp == null || cp.isEmpty()) { 74 String initialModuleName = System.getProperty("jdk.module.main"); 75 cp = (initialModuleName == null) ? "" : null; 76 } 77 URLClassPath ucp = new URLClassPath(cp, false); 78 APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp); 79 } 80 81 /** 82 * Returns the class loader that is used to find resources in modules 83 * defined to the boot class loader. 84 * 85 * @apiNote This method is not public, it should instead be used via 86 * the BootLoader class that provides a restricted API to this class 87 * loader. 88 */ 89 static BuiltinClassLoader bootLoader() { 90 return BOOT_LOADER; 91 } 92 93 /** 94 * Returns the platform class loader. 95 */ 96 public static ClassLoader platformClassLoader() { 97 return PLATFORM_LOADER; 98 } 99 100 /** 101 * Returns the application class loader. 102 */ 103 public static ClassLoader appClassLoader() { 104 return APP_LOADER; 105 } 106 107 /** 108 * The class loader that is used to find resources in modules defined to 109 * the boot class loader. It is not used for class loading. 110 */ 111 private static class BootClassLoader extends BuiltinClassLoader { 112 BootClassLoader(URLClassPath bcp) { 113 super(null, null, bcp); 114 } 115 116 @Override 117 protected Class<?> loadClassOrNull(String cn) { 118 return JLA.findBootstrapClassOrNull(this, cn); 119 } 120 }; 121 122 /** 123 * The platform class loader, a unique type to make it easier to distinguish 124 * from the application class loader. 125 */ 126 private static class PlatformClassLoader extends BuiltinClassLoader { 127 static { 128 if (!ClassLoader.registerAsParallelCapable()) 129 throw new InternalError(); 130 } 131 132 PlatformClassLoader(BootClassLoader parent) { 133 super("platform", parent, null); 134 } 135 136 /** 137 * Called by the VM to support define package for AppCDS. 138 * 139 * Shared classes are returned in ClassLoader::findLoadedClass 140 * that bypass the defineClass call. 141 */ 142 private Package definePackage(String pn, Module module) { 143 return JLA.definePackage(this, pn, module); 144 } 145 } 146 147 /** 148 * The application class loader that is a {@code BuiltinClassLoader} with 149 * customizations to be compatible with long standing behavior. 150 */ 151 private static class AppClassLoader extends BuiltinClassLoader { 152 static { 153 if (!ClassLoader.registerAsParallelCapable()) 154 throw new InternalError(); 155 } 156 157 final URLClassPath ucp; 158 159 AppClassLoader(PlatformClassLoader parent, URLClassPath ucp) { 160 super("app", parent, ucp); 161 this.ucp = ucp; 162 } 163 164 @Override 165 protected Class<?> loadClass(String cn, boolean resolve) 166 throws ClassNotFoundException 167 { 168 // for compatibility reasons, say where restricted package list has 169 // been updated to list API packages in the unnamed module. 170 SecurityManager sm = System.getSecurityManager(); 171 if (sm != null) { 172 int i = cn.lastIndexOf('.'); 173 if (i != -1) { 174 sm.checkPackageAccess(cn.substring(0, i)); 175 } 176 } 177 178 return super.loadClass(cn, resolve); 179 } 180 181 @Override 182 protected PermissionCollection getPermissions(CodeSource cs) { 183 PermissionCollection perms = super.getPermissions(cs); 184 perms.add(new RuntimePermission("exitVM")); 185 return perms; 186 } 187 188 /** 189 * Called by the VM to support dynamic additions to the class path 190 * 191 * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch 192 */ 193 void appendToClassPathForInstrumentation(String path) { 194 ucp.addFile(path); 195 } 196 197 /** 198 * Called by the VM to support define package for AppCDS 199 * 200 * Shared classes are returned in ClassLoader::findLoadedClass 201 * that bypass the defineClass call. 202 */ 203 private Package definePackage(String pn, Module module) { 204 return JLA.definePackage(this, pn, module); 205 } 206 207 /** 208 * Called by the VM to support define package for AppCDS 209 */ 210 protected Package defineOrCheckPackage(String pn, Manifest man, URL url) { 211 return super.defineOrCheckPackage(pn, man, url); 212 } 213 } 214 215 /** 216 * Attempts to convert the given string to a file URL. 217 * 218 * @apiNote This is called by the VM 219 */ 220 @Deprecated 221 private static URL toFileURL(String s) { 222 try { 223 // Use an intermediate File object to construct a URI/URL without 224 // authority component as URLClassPath can't handle URLs with a UNC 225 // server name in the authority component. 226 return Path.of(s).toRealPath().toFile().toURI().toURL(); 227 } catch (InvalidPathException | IOException ignore) { 228 // malformed path string or class path element does not exist 229 return null; 230 } 231 } 232 }