src/java.base/share/classes/java/net/URLClassLoader.java

Print this page
rev 10599 : 8057936: java.net.URLClassLoader.findClass uses exceptions in control flow


  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 java.net;
  27 
  28 import java.io.Closeable;
  29 import java.io.File;
  30 import java.io.FilePermission;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.CodeSigner;
  36 import java.security.CodeSource;
  37 import java.security.Permission;
  38 import java.security.PermissionCollection;
  39 import java.security.PrivilegedAction;
  40 import java.security.PrivilegedExceptionAction;
  41 import java.security.SecureClassLoader;
  42 import java.util.Enumeration;
  43 import java.util.List;
  44 import java.util.NoSuchElementException;
  45 import java.util.Objects;
  46 import java.util.Set;
  47 import java.util.WeakHashMap;
  48 import java.util.jar.Attributes;
  49 import java.util.jar.Attributes.Name;
  50 import java.util.jar.JarFile;
  51 import java.util.jar.Manifest;
  52 import sun.misc.Resource;
  53 import sun.misc.URLClassPath;
  54 import sun.net.www.ParseUtil;
  55 import sun.security.util.SecurityConstants;
  56 
  57 /**
  58  * This class loader is used to load classes and resources from a search
  59  * path of URLs referring to both JAR files and directories. Any URL that
  60  * ends with a '/' is assumed to refer to a directory. Otherwise, the URL


 326      * list of URLs, or if this loader is closed, then invoking this
 327      * method has no effect.
 328      *
 329      * @param url the URL to be added to the search path of URLs
 330      */
 331     protected void addURL(URL url) {
 332         ucp.addURL(url);
 333     }
 334 
 335     /**
 336      * Returns the search path of URLs for loading classes and resources.
 337      * This includes the original list of URLs specified to the constructor,
 338      * along with any URLs subsequently appended by the addURL() method.
 339      * @return the search path of URLs for loading classes and resources.
 340      */
 341     public URL[] getURLs() {
 342         return ucp.getURLs();
 343     }
 344 
 345     /**
































 346      * Finds and loads the class with the specified name from the URL search
 347      * path. Any URLs referring to JAR files are loaded and opened as needed
 348      * until the class is found.
 349      *
 350      * @param name the name of the class
 351      * @return the resulting class
 352      * @exception ClassNotFoundException if the class could not be found,
 353      *            or if the loader is closed.
 354      * @exception NullPointerException if {@code name} is {@code null}.
 355      */
 356     protected Class<?> findClass(final String name)
 357          throws ClassNotFoundException
 358     {
 359         try {
 360             return AccessController.doPrivileged(
 361                 new PrivilegedExceptionAction<Class<?>>() {
 362                     public Class<?> run() throws ClassNotFoundException {
 363                         String path = name.replace('.', '/').concat(".class");
 364                         Resource res = ucp.getResource(path, false);
 365                         if (res != null) {
 366                             try {
 367                                 return defineClass(name, res);
 368                             } catch (IOException e) {
 369                                 throw new ClassNotFoundException(name, e);
 370                             }
 371                         } else {
 372                             throw new ClassNotFoundException(name);
 373                         }
 374                     }
 375                 }, acc);
 376         } catch (java.security.PrivilegedActionException pae) {
 377             throw (ClassNotFoundException) pae.getException();
 378         }

 379     }
 380 
 381     /*
 382      * Retrieve the package using the specified package name.
 383      * If non-null, verify the package using the specified code
 384      * source and manifest.
 385      */
 386     private Package getAndVerifyPackage(String pkgname,
 387                                         Manifest man, URL url) {
 388         Package pkg = getPackage(pkgname);
 389         if (pkg != null) {
 390             // Package found, so check package sealing.
 391             if (pkg.isSealed()) {
 392                 // Verify that code source URL is the same.
 393                 if (!pkg.isSealed(url)) {
 394                     throw new SecurityException(
 395                         "sealing violation: package " + pkgname + " is sealed");
 396                 }
 397             } else {
 398                 // Make sure we are not attempting to seal the package




  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 java.net;
  27 
  28 import java.io.Closeable;
  29 import java.io.File;
  30 import java.io.FilePermission;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.CodeSigner;
  36 import java.security.CodeSource;
  37 import java.security.Permission;
  38 import java.security.PermissionCollection;
  39 import java.security.PrivilegedAction;

  40 import java.security.SecureClassLoader;
  41 import java.util.Enumeration;
  42 import java.util.List;
  43 import java.util.NoSuchElementException;
  44 import java.util.Objects;
  45 import java.util.Set;
  46 import java.util.WeakHashMap;
  47 import java.util.jar.Attributes;
  48 import java.util.jar.Attributes.Name;
  49 import java.util.jar.JarFile;
  50 import java.util.jar.Manifest;
  51 import sun.misc.Resource;
  52 import sun.misc.URLClassPath;
  53 import sun.net.www.ParseUtil;
  54 import sun.security.util.SecurityConstants;
  55 
  56 /**
  57  * This class loader is used to load classes and resources from a search
  58  * path of URLs referring to both JAR files and directories. Any URL that
  59  * ends with a '/' is assumed to refer to a directory. Otherwise, the URL


 325      * list of URLs, or if this loader is closed, then invoking this
 326      * method has no effect.
 327      *
 328      * @param url the URL to be added to the search path of URLs
 329      */
 330     protected void addURL(URL url) {
 331         ucp.addURL(url);
 332     }
 333 
 334     /**
 335      * Returns the search path of URLs for loading classes and resources.
 336      * This includes the original list of URLs specified to the constructor,
 337      * along with any URLs subsequently appended by the addURL() method.
 338      * @return the search path of URLs for loading classes and resources.
 339      */
 340     public URL[] getURLs() {
 341         return ucp.getURLs();
 342     }
 343 
 344     /**
 345      * Wrap result of privileged action to avoid having to raise
 346      * PrivilegedActionException when class is not found.
 347      */
 348     private static class FindClassResult {
 349         private final Class<?> foundClass;
 350         private final Throwable throwable;
 351         private final String name;
 352 
 353         FindClassResult(Class<?> foundClass) {
 354             this(foundClass, null, null);
 355         }
 356 
 357         FindClassResult(Class<?> foundClass, Throwable t, String name) {
 358             this.foundClass = foundClass;
 359             this.throwable = t;
 360             this.name = name;
 361         }
 362 
 363         Class<?> getFoundClass() {
 364             return foundClass;
 365         }
 366 
 367         Throwable getThrowable() {
 368             return throwable;
 369         }
 370 
 371         String getName() {
 372             return name;
 373         }
 374     }
 375 
 376     /**
 377      * Finds and loads the class with the specified name from the URL search
 378      * path. Any URLs referring to JAR files are loaded and opened as needed
 379      * until the class is found.
 380      *
 381      * @param name the name of the class
 382      * @return the resulting class
 383      * @exception ClassNotFoundException if the class could not be found,
 384      *            or if the loader is closed.
 385      * @exception NullPointerException if {@code name} is {@code null}.
 386      */
 387     protected Class<?> findClass(final String name)
 388          throws ClassNotFoundException
 389     {
 390         Objects.requireNonNull(name);
 391         FindClassResult result = AccessController.doPrivileged(
 392             new PrivilegedAction<FindClassResult>() {
 393                 public FindClassResult run() {
 394                     String path = name.replace('.', '/').concat(".class");
 395                     Resource res = ucp.getResource(path, false);
 396                     if (res != null) {
 397                         try {
 398                             return new FindClassResult(defineClass(name, res));
 399                         } catch (IOException e) {
 400                             return new FindClassResult(null, e, name);
 401                         }
 402                     } else {
 403                         return new FindClassResult(null, null, name);
 404                     }
 405                 }
 406             }, acc);
 407         if (result.getFoundClass() != null) {
 408             return result.getFoundClass();
 409         }
 410         throw new ClassNotFoundException(result.getName(), result.getThrowable());
 411     }
 412 
 413     /*
 414      * Retrieve the package using the specified package name.
 415      * If non-null, verify the package using the specified code
 416      * source and manifest.
 417      */
 418     private Package getAndVerifyPackage(String pkgname,
 419                                         Manifest man, URL url) {
 420         Package pkg = getPackage(pkgname);
 421         if (pkg != null) {
 422             // Package found, so check package sealing.
 423             if (pkg.isSealed()) {
 424                 // Verify that code source URL is the same.
 425                 if (!pkg.isSealed(url)) {
 426                     throw new SecurityException(
 427                         "sealing violation: package " + pkgname + " is sealed");
 428                 }
 429             } else {
 430                 // Make sure we are not attempting to seal the package