src/java.base/share/classes/java/lang/ClassLoader.java

Print this page
rev 10764 : 8060130: Simplify the synchronization of defining and getting java.lang.Package
Reviewed-by: mchung


  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 package java.lang;
  26 
  27 import java.io.InputStream;
  28 import java.io.IOException;
  29 import java.io.File;
  30 import java.lang.reflect.Constructor;
  31 import java.lang.reflect.InvocationTargetException;
  32 import java.net.MalformedURLException;
  33 import java.net.URL;
  34 import java.security.AccessController;
  35 import java.security.AccessControlContext;
  36 import java.security.CodeSource;
  37 import java.security.Policy;
  38 import java.security.PrivilegedAction;
  39 import java.security.PrivilegedActionException;
  40 import java.security.PrivilegedExceptionAction;
  41 import java.security.ProtectionDomain;
  42 import java.security.cert.Certificate;
  43 import java.util.Collections;
  44 import java.util.Enumeration;
  45 import java.util.HashMap;
  46 import java.util.HashSet;
  47 import java.util.Set;
  48 import java.util.Stack;
  49 import java.util.Map;
  50 import java.util.Vector;
  51 import java.util.Hashtable;
  52 import java.util.WeakHashMap;
  53 import java.util.concurrent.ConcurrentHashMap;
  54 import sun.misc.CompoundEnumeration;
  55 import sun.misc.Resource;
  56 import sun.misc.URLClassPath;
  57 import sun.misc.VM;
  58 import sun.reflect.CallerSensitive;
  59 import sun.reflect.Reflection;
  60 import sun.reflect.misc.ReflectUtil;
  61 import sun.security.util.SecurityConstants;
  62 
  63 /**
  64  * A class loader is an object that is responsible for loading classes. The
  65  * class <tt>ClassLoader</tt> is an abstract class.  Given the <a
  66  * href="#name">binary name</a> of a class, a class loader should attempt to
  67  * locate or generate data that constitutes a definition for the class.  A
  68  * typical strategy is to transform the name into a file name and then read a
  69  * "class file" of that name from a file system.
  70  *
  71  * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
  72  * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
  73  * it.
  74  *
  75  * <p> <tt>Class</tt> objects for array classes are not created by class
  76  * loaders, but are created automatically as required by the Java runtime.
  77  * The class loader for an array class, as returned by {@link


 252     // is to keep the classes from being GC'ed until the loader is GC'ed.
 253     private final Vector<Class<?>> classes = new Vector<>();
 254 
 255     // The "default" domain. Set as the default ProtectionDomain on newly
 256     // created classes.
 257     private final ProtectionDomain defaultDomain =
 258         new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
 259                              null, this, null);
 260 
 261     // The initiating protection domains for all classes loaded by this loader
 262     private final Set<ProtectionDomain> domains;
 263 
 264     // Invoked by the VM to record every loaded class with this loader.
 265     void addClass(Class<?> c) {
 266         classes.addElement(c);
 267     }
 268 
 269     // The packages defined in this class loader.  Each package name is mapped
 270     // to its corresponding Package object.
 271     // @GuardedBy("itself")
 272     private final HashMap<String, Package> packages = new HashMap<>();

 273 
 274     private static Void checkCreateClassLoader() {
 275         SecurityManager security = System.getSecurityManager();
 276         if (security != null) {
 277             security.checkCreateClassLoader();
 278         }
 279         return null;
 280     }
 281 
 282     private ClassLoader(Void unused, ClassLoader parent) {
 283         this.parent = parent;
 284         if (ParallelLoaders.isRegistered(this.getClass())) {
 285             parallelLockMap = new ConcurrentHashMap<>();
 286             package2certs = new ConcurrentHashMap<>();
 287             domains = Collections.synchronizedSet(new HashSet<>());
 288             assertionLock = new Object();
 289         } else {
 290             // no finer-grained lock; lock on the classloader instance
 291             parallelLockMap = null;
 292             package2certs = new Hashtable<>();


1558      *
1559      * @param  sealBase
1560      *         If not <tt>null</tt>, then this package is sealed with
1561      *         respect to the given code source {@link java.net.URL
1562      *         <tt>URL</tt>}  object.  Otherwise, the package is not sealed.
1563      *
1564      * @return  The newly defined <tt>Package</tt> object
1565      *
1566      * @throws  IllegalArgumentException
1567      *          If package name duplicates an existing package either in this
1568      *          class loader or one of its ancestors
1569      *
1570      * @since  1.2
1571      */
1572     protected Package definePackage(String name, String specTitle,
1573                                     String specVersion, String specVendor,
1574                                     String implTitle, String implVersion,
1575                                     String implVendor, URL sealBase)
1576         throws IllegalArgumentException
1577     {
1578         synchronized (packages) {
1579             Package pkg = getPackage(name);
1580             if (pkg != null) {
1581                 throw new IllegalArgumentException(name);
1582             }
1583             pkg = new Package(name, specTitle, specVersion, specVendor,
1584                               implTitle, implVersion, implVendor,
1585                               sealBase, this);
1586             packages.put(name, pkg);
1587             return pkg;
1588         }

1589     }
1590 
1591     /**
1592      * Returns a <tt>Package</tt> that has been defined by this class loader
1593      * or any of its ancestors.
1594      *
1595      * @param  name
1596      *         The package name
1597      *
1598      * @return  The <tt>Package</tt> corresponding to the given name, or
1599      *          <tt>null</tt> if not found
1600      *
1601      * @since  1.2
1602      */
1603     protected Package getPackage(String name) {
1604         Package pkg;
1605         synchronized (packages) {
1606             pkg = packages.get(name);
1607         }
1608         if (pkg == null) {
1609             if (parent != null) {
1610                 pkg = parent.getPackage(name);
1611             } else {
1612                 pkg = Package.getSystemPackage(name);
1613             }
1614             if (pkg != null) {
1615                 synchronized (packages) {
1616                     Package pkg2 = packages.get(name);
1617                     if (pkg2 == null) {
1618                         packages.put(name, pkg);
1619                     } else {
1620                         pkg = pkg2;
1621                     }
1622                 }
1623             }
1624         }
1625         return pkg;
1626     }
1627 
1628     /**
1629      * Returns all of the <tt>Packages</tt> defined by this class loader and
1630      * its ancestors.
1631      *
1632      * @return  The array of <tt>Package</tt> objects defined by this
1633      *          <tt>ClassLoader</tt>
1634      *
1635      * @since  1.2
1636      */
1637     protected Package[] getPackages() {
1638         Map<String, Package> map;
1639         synchronized (packages) {
1640             map = new HashMap<>(packages);
1641         }
1642         Package[] pkgs;
1643         if (parent != null) {
1644             pkgs = parent.getPackages();
1645         } else {
1646             pkgs = Package.getSystemPackages();
1647         }
1648         if (pkgs != null) {




1649             for (Package pkg : pkgs) {
1650                 String pkgName = pkg.getName();
1651                 if (map.get(pkgName) == null) {
1652                     map.put(pkgName, pkg);
1653                 }
1654             }
1655         }
1656         return map.values().toArray(new Package[map.size()]);

1657     }
1658 
1659 
1660     // -- Native library access --
1661 
1662     /**
1663      * Returns the absolute path name of a native library.  The VM invokes this
1664      * method to locate the native libraries that belong to classes loaded with
1665      * this class loader. If this method returns <tt>null</tt>, the VM
1666      * searches the library along the path specified as the
1667      * "<tt>java.library.path</tt>" property.
1668      *
1669      * @param  libname
1670      *         The library name
1671      *
1672      * @return  The absolute path of the native library
1673      *
1674      * @see  System#loadLibrary(String)
1675      * @see  System#mapLibraryName(String)
1676      *




  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 package java.lang;
  26 
  27 import java.io.InputStream;
  28 import java.io.IOException;
  29 import java.io.File;
  30 import java.lang.reflect.Constructor;
  31 import java.lang.reflect.InvocationTargetException;

  32 import java.net.URL;
  33 import java.security.AccessController;
  34 import java.security.AccessControlContext;
  35 import java.security.CodeSource;

  36 import java.security.PrivilegedAction;
  37 import java.security.PrivilegedActionException;
  38 import java.security.PrivilegedExceptionAction;
  39 import java.security.ProtectionDomain;
  40 import java.security.cert.Certificate;
  41 import java.util.Collections;
  42 import java.util.Enumeration;
  43 import java.util.HashMap;
  44 import java.util.HashSet;
  45 import java.util.Set;
  46 import java.util.Stack;
  47 import java.util.Map;
  48 import java.util.Vector;
  49 import java.util.Hashtable;
  50 import java.util.WeakHashMap;
  51 import java.util.concurrent.ConcurrentHashMap;
  52 import sun.misc.CompoundEnumeration;
  53 import sun.misc.Resource;
  54 import sun.misc.URLClassPath;

  55 import sun.reflect.CallerSensitive;
  56 import sun.reflect.Reflection;
  57 import sun.reflect.misc.ReflectUtil;
  58 import sun.security.util.SecurityConstants;
  59 
  60 /**
  61  * A class loader is an object that is responsible for loading classes. The
  62  * class <tt>ClassLoader</tt> is an abstract class.  Given the <a
  63  * href="#name">binary name</a> of a class, a class loader should attempt to
  64  * locate or generate data that constitutes a definition for the class.  A
  65  * typical strategy is to transform the name into a file name and then read a
  66  * "class file" of that name from a file system.
  67  *
  68  * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
  69  * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
  70  * it.
  71  *
  72  * <p> <tt>Class</tt> objects for array classes are not created by class
  73  * loaders, but are created automatically as required by the Java runtime.
  74  * The class loader for an array class, as returned by {@link


 249     // is to keep the classes from being GC'ed until the loader is GC'ed.
 250     private final Vector<Class<?>> classes = new Vector<>();
 251 
 252     // The "default" domain. Set as the default ProtectionDomain on newly
 253     // created classes.
 254     private final ProtectionDomain defaultDomain =
 255         new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
 256                              null, this, null);
 257 
 258     // The initiating protection domains for all classes loaded by this loader
 259     private final Set<ProtectionDomain> domains;
 260 
 261     // Invoked by the VM to record every loaded class with this loader.
 262     void addClass(Class<?> c) {
 263         classes.addElement(c);
 264     }
 265 
 266     // The packages defined in this class loader.  Each package name is mapped
 267     // to its corresponding Package object.
 268     // @GuardedBy("itself")
 269     private final ConcurrentHashMap<String, Package> packages
 270             = new ConcurrentHashMap<>();
 271 
 272     private static Void checkCreateClassLoader() {
 273         SecurityManager security = System.getSecurityManager();
 274         if (security != null) {
 275             security.checkCreateClassLoader();
 276         }
 277         return null;
 278     }
 279 
 280     private ClassLoader(Void unused, ClassLoader parent) {
 281         this.parent = parent;
 282         if (ParallelLoaders.isRegistered(this.getClass())) {
 283             parallelLockMap = new ConcurrentHashMap<>();
 284             package2certs = new ConcurrentHashMap<>();
 285             domains = Collections.synchronizedSet(new HashSet<>());
 286             assertionLock = new Object();
 287         } else {
 288             // no finer-grained lock; lock on the classloader instance
 289             parallelLockMap = null;
 290             package2certs = new Hashtable<>();


1556      *
1557      * @param  sealBase
1558      *         If not <tt>null</tt>, then this package is sealed with
1559      *         respect to the given code source {@link java.net.URL
1560      *         <tt>URL</tt>}  object.  Otherwise, the package is not sealed.
1561      *
1562      * @return  The newly defined <tt>Package</tt> object
1563      *
1564      * @throws  IllegalArgumentException
1565      *          If package name duplicates an existing package either in this
1566      *          class loader or one of its ancestors
1567      *
1568      * @since  1.2
1569      */
1570     protected Package definePackage(String name, String specTitle,
1571                                     String specVersion, String specVendor,
1572                                     String implTitle, String implVersion,
1573                                     String implVendor, URL sealBase)
1574         throws IllegalArgumentException
1575     {

1576         Package pkg = getPackage(name);
1577         if (pkg != null) {
1578             throw new IllegalArgumentException(name);
1579         }
1580         pkg = new Package(name, specTitle, specVersion, specVendor,
1581                           implTitle, implVersion, implVendor,
1582                           sealBase, this);
1583         // Races here can be safely dealt with by ensuring we always return
1584         // the same package object
1585         Package oldPkg = packages.putIfAbsent(name, pkg);
1586         return (oldPkg != null ? oldPkg : pkg);
1587     }
1588 
1589     /**
1590      * Returns a <tt>Package</tt> that has been defined by this class loader
1591      * or any of its ancestors.
1592      *
1593      * @param  name
1594      *         The package name
1595      *
1596      * @return  The <tt>Package</tt> corresponding to the given name, or
1597      *          <tt>null</tt> if not found
1598      *
1599      * @since  1.2
1600      */
1601     protected Package getPackage(String name) {
1602         Package pkg = packages.get(name);



1603         if (pkg == null) {
1604             if (parent != null) {
1605                 pkg = parent.getPackage(name);
1606             } else {
1607                 pkg = Package.getSystemPackage(name);
1608             }










1609         }
1610         return pkg;
1611     }
1612 
1613     /**
1614      * Returns all of the <tt>Packages</tt> defined by this class loader and
1615      * its ancestors.
1616      *
1617      * @return  The array of <tt>Package</tt> objects defined by this
1618      *          <tt>ClassLoader</tt>
1619      *
1620      * @since  1.2
1621      */
1622     protected Package[] getPackages() {
1623         Map<String, Package> map;



1624         Package[] pkgs;
1625         if (parent != null) {
1626             pkgs = parent.getPackages();
1627         } else {
1628             pkgs = Package.getSystemPackages();
1629         }
1630 
1631         if (pkgs == null) {
1632             map = packages;
1633         } else {
1634             map = new HashMap<>(packages);
1635             for (Package pkg : pkgs) {
1636                 String pkgName = pkg.getName();
1637                 if (!map.containsKey(pkgName)) {
1638                     map.put(pkgName, pkg);
1639                 }
1640             }
1641         }
1642         return map.values().toArray(new Package[map.size()]);
1643 
1644     }
1645 
1646 
1647     // -- Native library access --
1648 
1649     /**
1650      * Returns the absolute path name of a native library.  The VM invokes this
1651      * method to locate the native libraries that belong to classes loaded with
1652      * this class loader. If this method returns <tt>null</tt>, the VM
1653      * searches the library along the path specified as the
1654      * "<tt>java.library.path</tt>" property.
1655      *
1656      * @param  libname
1657      *         The library name
1658      *
1659      * @return  The absolute path of the native library
1660      *
1661      * @see  System#loadLibrary(String)
1662      * @see  System#mapLibraryName(String)
1663      *