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