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