src/java.base/share/classes/sun/misc/Launcher.java

Print this page




  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 sun.misc;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.io.FilePermission;
  31 import java.net.URL;
  32 import java.net.URLClassLoader;
  33 import java.net.MalformedURLException;
  34 import java.net.URLStreamHandler;
  35 import java.net.URLStreamHandlerFactory;

  36 import java.util.HashSet;

  37 import java.util.StringTokenizer;
  38 import java.util.Set;
  39 import java.util.Vector;
  40 import java.security.AccessController;
  41 import java.security.PrivilegedAction;
  42 import java.security.PrivilegedExceptionAction;
  43 import java.security.AccessControlContext;
  44 import java.security.PermissionCollection;
  45 import java.security.Permissions;
  46 import java.security.Permission;
  47 import java.security.ProtectionDomain;
  48 import java.security.CodeSource;
  49 import sun.security.util.SecurityConstants;
  50 import sun.net.www.ParseUtil;
  51 
  52 /**
  53  * This class is used by the system to launch the main application.
  54 Launcher */
  55 public class Launcher {






  56     private static URLStreamHandlerFactory factory = new Factory();
  57     private static Launcher launcher = new Launcher();
  58     private static String bootClassPath =
  59         System.getProperty("sun.boot.class.path");
  60 
  61     public static Launcher getLauncher() {
  62         return launcher;
  63     }
  64 
  65     private ClassLoader loader;
  66 
  67     public Launcher() {
  68         // Create the extension class loader
  69         ClassLoader extcl;
  70         try {
  71             extcl = ExtClassLoader.getExtClassLoader();
  72         } catch (IOException e) {
  73             throw new InternalError(
  74                 "Could not create extension class loader", e);
  75         }
  76 
  77         // Now create the class loader to use to launch the application
  78         try {
  79             loader = AppClassLoader.getAppClassLoader(extcl);


 112     /*
 113      * Returns the class loader used to launch the main application.
 114      */
 115     public ClassLoader getClassLoader() {
 116         return loader;
 117     }
 118 
 119     /*
 120      * The class loader used for loading installed extensions.
 121      */
 122     static class ExtClassLoader extends URLClassLoader {
 123 
 124         static {
 125             ClassLoader.registerAsParallelCapable();
 126         }
 127 
 128         /**
 129          * create an ExtClassLoader. The ExtClassLoader is created
 130          * within a context that limits which files it can read
 131          */
 132         public static ExtClassLoader getExtClassLoader() throws IOException
 133         {
 134             final File[] dirs = getExtDirs();
 135 
 136             try {
 137                 // Prior implementations of this doPrivileged() block supplied
 138                 // aa synthesized ACC via a call to the private method
 139                 // ExtClassLoader.getContext().
 140 
 141                 return AccessController.doPrivileged(
 142                     new PrivilegedExceptionAction<ExtClassLoader>() {
 143                         public ExtClassLoader run() throws IOException {
 144                             int len = dirs.length;
 145                             for (int i = 0; i < len; i++) {
 146                                 MetaIndex.registerDirectory(dirs[i]);
 147                             }
 148                             return new ExtClassLoader(dirs);




 149                         }
 150                     });
 151             } catch (java.security.PrivilegedActionException e) {
 152                 throw (IOException) e.getException();
 153             }
 154         }
 155 
 156         void addExtURL(URL url) {
 157             super.addURL(url);
 158         }
 159 
 160         /*
 161          * Creates a new ExtClassLoader for the specified directories.
 162          */
 163         public ExtClassLoader(File[] dirs) throws IOException {
 164             super(getExtURLs(dirs), null, factory);
 165         }
 166 
 167         private static File[] getExtDirs() {
 168             String s = System.getProperty("java.ext.dirs");
 169             File[] dirs;
 170             if (s != null) {
 171                 StringTokenizer st =
 172                     new StringTokenizer(s, File.pathSeparator);
 173                 int count = st.countTokens();
 174                 dirs = new File[count];
 175                 for (int i = 0; i < count; i++) {
 176                     dirs[i] = new File(st.nextToken());
 177                 }
 178             } else {
 179                 dirs = new File[0];
 180             }
 181             return dirs;
 182         }
 183 
 184         private static URL[] getExtURLs(File[] dirs) throws IOException {
 185             Vector<URL> urls = new Vector<URL>();
 186             for (int i = 0; i < dirs.length; i++) {
 187                 String[] files = dirs[i].list();
 188                 if (files != null) {
 189                     for (int j = 0; j < files.length; j++) {
 190                         if (!files[j].equals("meta-index")) {
 191                             File f = new File(dirs[i], files[j]);
 192                             urls.add(getFileURL(f));
 193                         }
 194                     }
 195                 }
 196             }
 197             URL[] ua = new URL[urls.size()];
 198             urls.copyInto(ua);
 199             return ua;
 200         }
 201 
 202         /*
 203          * Searches the installed extension directories for the specified
 204          * library name. For each extension directory, we first look for
 205          * the native library in the subdirectory whose name is the value
 206          * of the system property <code>os.arch</code>. Failing that, we
 207          * look in the extension directory itself.
 208          */
 209         public String findLibrary(String name) {
 210             final String libname = System.mapLibraryName(name);
 211             URL[] urls = super.getURLs();
 212             File prevDir = null;
 213             for (int i = 0; i < urls.length; i++) {
 214                 // Get the ext directory from the URL
 215                 File dir = new File(urls[i].getPath()).getParentFile();
 216                 if (dir != null && !dir.equals(prevDir)) {
 217                     // Look in architecture-specific subdirectory first
 218                     // Read from the saved system properties to avoid deadlock
 219                     final String arch = VM.getSavedProperty("os.arch");
 220                     String pathname = AccessController.doPrivileged(
 221                         new PrivilegedAction<String>() {
 222                             public String run() {
 223                                 if (arch != null) {
 224                                     File file = new File(new File(dir, arch), libname);
 225                                     if (file.exists()) {
 226                                         return file.getAbsolutePath();
 227                                     }
 228                                 }
 229                                 // Then check the extension directory
 230                                 File file = new File(dir, libname);
 231                                 if (file.exists()) {
 232                                     return file.getAbsolutePath();
 233                                 }
 234                                 return null;
 235                             }
 236                         });
 237                     if (pathname != null) {
 238                         return pathname;
 239                     }
 240                 }
 241                 prevDir = dir;
 242             }
 243             return null;
 244         }
 245 
 246         private static AccessControlContext getContext(File[] dirs)
 247             throws IOException
 248         {
 249             PathPermissions perms =
 250                 new PathPermissions(dirs);
 251 
 252             ProtectionDomain domain = new ProtectionDomain(
 253                 new CodeSource(perms.getCodeBase(),
 254                     (java.security.cert.Certificate[]) null),
 255                 perms);
 256 
 257             AccessControlContext acc =
 258                 new AccessControlContext(new ProtectionDomain[] { domain });
 259 
 260             return acc;
 261         }
 262     }
 263 
 264     /**
 265      * The class loader used for loading from java.class.path.
 266      * runs in a restricted security context.
 267      */
 268     static class AppClassLoader extends URLClassLoader {
 269 
 270         static {
 271             ClassLoader.registerAsParallelCapable();
 272         }
 273 
 274         public static ClassLoader getAppClassLoader(final ClassLoader extcl)
 275             throws IOException
 276         {
 277             final String s = System.getProperty("java.class.path");
 278             final File[] path = (s == null) ? new File[0] : getClassPath(s, true);










 279 
 280             // Note: on bugid 4256530
 281             // Prior implementations of this doPrivileged() block supplied
 282             // a rather restrictive ACC via a call to the private method
 283             // AppClassLoader.getContext(). This proved overly restrictive
 284             // when loading  classes. Specifically it prevent
 285             // accessClassInPackage.sun.* grants from being honored.
 286             //
 287             return AccessController.doPrivileged(
 288                 new PrivilegedAction<AppClassLoader>() {
 289                     public AppClassLoader run() {
 290                     URL[] urls =
 291                         (s == null) ? new URL[0] : pathToURLs(path);
 292                     return new AppClassLoader(urls, extcl);
 293                 }
 294             });
 295         }
 296 
 297         /*
 298          * Creates a new AppClassLoader
 299          */
 300         AppClassLoader(URL[] urls, ClassLoader parent) {
 301             super(urls, parent, factory);
 302         }
 303 
 304         /**
 305          * Override loadClass so we can checkPackageAccess.
 306          */
 307         public Class<?> loadClass(String name, boolean resolve)
 308             throws ClassNotFoundException
 309         {
 310             int i = name.lastIndexOf('.');
 311             if (i != -1) {
 312                 SecurityManager sm = System.getSecurityManager();
 313                 if (sm != null) {
 314                     sm.checkPackageAccess(name.substring(0, i));
 315                 }
 316             }
 317             return (super.loadClass(name, resolve));
 318         }
 319 
 320         /**
 321          * allow any classes loaded from classpath to exit the VM.
 322          */
 323         protected PermissionCollection getPermissions(CodeSource codesource)
 324         {
 325             PermissionCollection perms = super.getPermissions(codesource);
 326             perms.add(new RuntimePermission("exitVM"));
 327             return perms;
 328         }
 329 
 330         /**
 331          * This class loader supports dynamic additions to the class path
 332          * at runtime.
 333          *
 334          * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
 335          */
 336         private void appendToClassPathForInstrumentation(String path) {
 337             assert(Thread.holdsLock(this));
 338 
 339             // addURL is a no-op if path already contains the URL
 340             super.addURL( getFileURL(new File(path)) );
 341         }
 342 
 343         /**
 344          * create a context that can read any directories (recursively)


 351             throws java.net.MalformedURLException
 352         {
 353             PathPermissions perms =
 354                 new PathPermissions(cp);
 355 
 356             ProtectionDomain domain =
 357                 new ProtectionDomain(new CodeSource(perms.getCodeBase(),
 358                     (java.security.cert.Certificate[]) null),
 359                 perms);
 360 
 361             AccessControlContext acc =
 362                 new AccessControlContext(new ProtectionDomain[] { domain });
 363 
 364             return acc;
 365         }
 366     }
 367 
 368     private static class BootClassPathHolder {
 369         static final URLClassPath bcp;
 370         static {
 371             URL[] urls;
 372             if (bootClassPath != null) {
 373                 urls = AccessController.doPrivileged(
 374                     new PrivilegedAction<URL[]>() {
 375                         public URL[] run() {



 376                             // Skip empty path in boot class path i.e. not default to use CWD
 377                             File[] classPath = getClassPath(bootClassPath, false);
 378                             int len = classPath.length;
 379                             Set<File> seenDirs = new HashSet<File>();
 380                             for (int i = 0; i < len; i++) {
 381                                 File curEntry = classPath[i];
 382                                 // Negative test used to properly handle
 383                                 // nonexistent jars on boot class path
 384                                 if (!curEntry.isDirectory()) {
 385                                     curEntry = curEntry.getParentFile();
 386                                 }
 387                                 if (curEntry != null && seenDirs.add(curEntry)) {
 388                                     MetaIndex.registerDirectory(curEntry);
 389                                 }
 390                             }
 391                             return pathToURLs(classPath);
 392                         }
 393                     }
 394                 );
 395             } else {
 396                 urls = new URL[0];
 397             }
 398             bcp = new URLClassPath(urls, factory);
 399         }
 400     }
 401 
 402     public static URLClassPath getBootstrapClassPath() {
 403         return BootClassPathHolder.bcp;
 404     }
 405 
 406     private static URL[] pathToURLs(File[] path) {
 407         URL[] urls = new URL[path.length];
 408         for (int i = 0; i < path.length; i++) {
 409             urls[i] = getFileURL(path[i]);
 410         }
 411         // DEBUG
 412         //for (int i = 0; i < urls.length; i++) {
 413         //  System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"');
 414         //}
 415         return urls;
 416     }
 417 




  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 sun.misc;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.io.FilePermission;
  31 import java.net.URL;
  32 import java.net.URLClassLoader;
  33 import java.net.MalformedURLException;
  34 import java.net.URLStreamHandler;
  35 import java.net.URLStreamHandlerFactory;
  36 import java.util.ArrayList;
  37 import java.util.HashSet;
  38 import java.util.List;
  39 import java.util.StringTokenizer;
  40 import java.util.Set;

  41 import java.security.AccessController;
  42 import java.security.PrivilegedAction;
  43 import java.security.PrivilegedExceptionAction;
  44 import java.security.AccessControlContext;
  45 import java.security.PermissionCollection;
  46 import java.security.Permissions;
  47 import java.security.Permission;
  48 import java.security.ProtectionDomain;
  49 import java.security.CodeSource;
  50 import sun.security.util.SecurityConstants;
  51 import sun.net.www.ParseUtil;
  52 
  53 /**
  54  * This class is used by the system to launch the main application.
  55 Launcher */
  56 public class Launcher {
  57 
  58     // ensure URLClassPath for boot loader is initialized first
  59     static {
  60         URLClassPath ucp = BootClassPathHolder.bcp;
  61     }
  62 
  63     private static URLStreamHandlerFactory factory = new Factory();
  64     private static Launcher launcher = new Launcher();


  65 
  66     public static Launcher getLauncher() {
  67         return launcher;
  68     }
  69 
  70     private ClassLoader loader;
  71 
  72     public Launcher() {
  73         // Create the extension class loader
  74         ClassLoader extcl;
  75         try {
  76             extcl = ExtClassLoader.getExtClassLoader();
  77         } catch (IOException e) {
  78             throw new InternalError(
  79                 "Could not create extension class loader", e);
  80         }
  81 
  82         // Now create the class loader to use to launch the application
  83         try {
  84             loader = AppClassLoader.getAppClassLoader(extcl);


 117     /*
 118      * Returns the class loader used to launch the main application.
 119      */
 120     public ClassLoader getClassLoader() {
 121         return loader;
 122     }
 123 
 124     /*
 125      * The class loader used for loading installed extensions.
 126      */
 127     static class ExtClassLoader extends URLClassLoader {
 128 
 129         static {
 130             ClassLoader.registerAsParallelCapable();
 131         }
 132 
 133         /**
 134          * create an ExtClassLoader. The ExtClassLoader is created
 135          * within a context that limits which files it can read
 136          */
 137         public static ExtClassLoader getExtClassLoader() throws IOException {



 138             try {
 139                 // Prior implementations of this doPrivileged() block supplied
 140                 // aa synthesized ACC via a call to the private method
 141                 // ExtClassLoader.getContext().
 142 
 143                 return AccessController.doPrivileged(
 144                     new PrivilegedExceptionAction<ExtClassLoader>() {
 145                         public ExtClassLoader run() throws IOException {
 146                             // ext modules linked into image
 147                             String home = System.getProperty("java.home");
 148                             File dir = new File(new File(home, "lib"), "modules");
 149                             File jimage = new File(dir, "extmodules.jimage");
 150 
 151                             File jfxrt = new File(new File(home, "lib"), "jfxrt.jar");
 152                             File[] files = jfxrt.exists() ? new File[] {jimage, jfxrt}
 153                                                           : new File[] {jimage};
 154                             return new ExtClassLoader(files);
 155                         }
 156                     });
 157             } catch (java.security.PrivilegedActionException e) {
 158                 throw (IOException) e.getException();
 159             }
 160         }
 161 
 162         void addExtURL(URL url) {
 163             super.addURL(url);
 164         }
 165 
 166         /*
 167          * Creates a new ExtClassLoader for the specified directories.
 168          */
 169         public ExtClassLoader(File[] files) throws IOException {
 170             super(getExtURLs(files), null, factory);
 171         }
 172 
 173         private static URL[] getExtURLs(File[] files) throws IOException {
 174             List<URL> urls = new ArrayList<>();
 175             for (File f : files) {






















 176                 urls.add(getFileURL(f));
 177             }
 178             return urls.toArray(new URL[0]);

















































 179         }
 180 
 181         private static AccessControlContext getContext(File[] dirs)
 182             throws IOException
 183         {
 184             PathPermissions perms =
 185                 new PathPermissions(dirs);
 186 
 187             ProtectionDomain domain = new ProtectionDomain(
 188                 new CodeSource(perms.getCodeBase(),
 189                     (java.security.cert.Certificate[]) null),
 190                 perms);
 191 
 192             AccessControlContext acc =
 193                 new AccessControlContext(new ProtectionDomain[] { domain });
 194 
 195             return acc;
 196         }
 197     }
 198 
 199     /**
 200      * The class loader used for loading from java.class.path.
 201      * runs in a restricted security context.
 202      */
 203     static class AppClassLoader extends URLClassLoader {
 204 
 205         static {
 206             ClassLoader.registerAsParallelCapable();
 207         }
 208 
 209         public static ClassLoader getAppClassLoader(final ClassLoader extcl)
 210             throws IOException
 211         {
 212             // modules linked into image are prepended to class path
 213             String home = System.getProperty("java.home");
 214             File dir = new File(new File(home, "lib"), "modules");
 215             String jimage = new File(dir, "appmodules.jimage").getPath();
 216 
 217             String cp = System.getProperty("java.class.path");
 218             if (cp == null) {
 219                 cp = jimage;
 220             } else {
 221                 cp = jimage + File.pathSeparator + cp;
 222             }
 223             final File[] path = getClassPath(cp, true);
 224 
 225             // Note: on bugid 4256530
 226             // Prior implementations of this doPrivileged() block supplied
 227             // a rather restrictive ACC via a call to the private method
 228             // AppClassLoader.getContext(). This proved overly restrictive
 229             // when loading  classes. Specifically it prevent
 230             // accessClassInPackage.sun.* grants from being honored.
 231             //
 232             return AccessController.doPrivileged(
 233                 new PrivilegedAction<AppClassLoader>() {
 234                     public AppClassLoader run() {
 235                         URL[] urls = pathToURLs(path);

 236                         return new AppClassLoader(urls, extcl);
 237                 }
 238             });
 239         }
 240 
 241         /*
 242          * Creates a new AppClassLoader
 243          */
 244         AppClassLoader(URL[] urls, ClassLoader parent) {
 245             super(urls, parent, factory);
 246         }
 247 
 248         /**
 249          * Override loadClass so we can checkPackageAccess.
 250          */
 251         public Class<?> loadClass(String name, boolean resolve)
 252             throws ClassNotFoundException
 253         {
 254             int i = name.lastIndexOf('.');
 255             if (i != -1) {
 256                 SecurityManager sm = System.getSecurityManager();
 257                 if (sm != null) {
 258                     sm.checkPackageAccess(name.substring(0, i));
 259                 }
 260             }
 261             return (super.loadClass(name, resolve));
 262         }
 263 
 264         /**
 265          * allow any classes loaded from classpath to exit the VM.
 266          */
 267         protected PermissionCollection getPermissions(CodeSource codesource) {

 268             PermissionCollection perms = super.getPermissions(codesource);
 269             perms.add(new RuntimePermission("exitVM"));
 270             return perms;
 271         }
 272 
 273         /**
 274          * This class loader supports dynamic additions to the class path
 275          * at runtime.
 276          *
 277          * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
 278          */
 279         private void appendToClassPathForInstrumentation(String path) {
 280             assert(Thread.holdsLock(this));
 281 
 282             // addURL is a no-op if path already contains the URL
 283             super.addURL( getFileURL(new File(path)) );
 284         }
 285 
 286         /**
 287          * create a context that can read any directories (recursively)


 294             throws java.net.MalformedURLException
 295         {
 296             PathPermissions perms =
 297                 new PathPermissions(cp);
 298 
 299             ProtectionDomain domain =
 300                 new ProtectionDomain(new CodeSource(perms.getCodeBase(),
 301                     (java.security.cert.Certificate[]) null),
 302                 perms);
 303 
 304             AccessControlContext acc =
 305                 new AccessControlContext(new ProtectionDomain[] { domain });
 306 
 307             return acc;
 308         }
 309     }
 310 
 311     private static class BootClassPathHolder {
 312         static final URLClassPath bcp;
 313         static {
 314             URL[] urls = AccessController.doPrivileged(


 315                     new PrivilegedAction<URL[]>() {
 316                         public URL[] run() {
 317                             String bootClassPath = System.getProperty("sun.boot.class.path");
 318                             if (bootClassPath == null)
 319                                 return new URL[0];
 320                             // Skip empty path in boot class path i.e. not default to use CWD
 321                             File[] classPath = getClassPath(bootClassPath, false);
 322                             int len = classPath.length;
 323                             Set<File> seenDirs = new HashSet<File>();
 324                             for (int i = 0; i < len; i++) {
 325                                 File curEntry = classPath[i];
 326                                 // Negative test used to properly handle
 327                                 // nonexistent jars on boot class path
 328                                 if (!curEntry.isDirectory()) {
 329                                     curEntry = curEntry.getParentFile();
 330                                 }
 331                                 if (curEntry != null && seenDirs.add(curEntry)) {
 332                                     MetaIndex.registerDirectory(curEntry);
 333                                 }
 334                             }
 335                             return pathToURLs(classPath);
 336                         }
 337                     }
 338                 );



 339             bcp = new URLClassPath(urls, factory);
 340         }
 341     }
 342 
 343     public static URLClassPath getBootstrapClassPath() {
 344         return BootClassPathHolder.bcp;
 345     }
 346 
 347     private static URL[] pathToURLs(File[] path) {
 348         URL[] urls = new URL[path.length];
 349         for (int i = 0; i < path.length; i++) {
 350             urls[i] = getFileURL(path[i]);
 351         }
 352         // DEBUG
 353         //for (int i = 0; i < urls.length; i++) {
 354         //  System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"');
 355         //}
 356         return urls;
 357     }
 358