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

Print this page
rev 10786 : 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


 251     // The classes loaded by this class loader. The only purpose of this table
 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      *




  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


 248     // The classes loaded by this class loader. The only purpose of this table
 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     private final ConcurrentHashMap<String, Package> packages
 269             = new ConcurrentHashMap<>();
 270 
 271     private static Void checkCreateClassLoader() {
 272         SecurityManager security = System.getSecurityManager();
 273         if (security != null) {
 274             security.checkCreateClassLoader();
 275         }
 276         return null;
 277     }
 278 
 279     private ClassLoader(Void unused, ClassLoader parent) {
 280         this.parent = parent;
 281         if (ParallelLoaders.isRegistered(this.getClass())) {
 282             parallelLockMap = new ConcurrentHashMap<>();
 283             package2certs = new ConcurrentHashMap<>();
 284             domains = Collections.synchronizedSet(new HashSet<>());
 285             assertionLock = new Object();
 286         } else {
 287             // no finer-grained lock; lock on the classloader instance
 288             parallelLockMap = null;
 289             package2certs = new Hashtable<>();


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

1575         Package pkg = getPackage(name);
1576         if (pkg != null) {
1577             throw new IllegalArgumentException(name);
1578         }
1579         pkg = new Package(name, specTitle, specVersion, specVendor,
1580                           implTitle, implVersion, implVendor,
1581                           sealBase, this);
1582         Package oldPkg = packages.putIfAbsent(name, pkg);
1583         if (oldPkg != null) {
1584             throw new IllegalArgumentException(name);
1585         }
1586         return 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         Package[] pkgs;
1624         if (parent != null) {
1625             pkgs = parent.getPackages();
1626         } else {
1627             pkgs = Package.getSystemPackages();
1628         }
1629 
1630         Map<String, Package> map = packages;
1631         if (pkgs != null) {
1632             map = new HashMap<>(packages);
1633             for (Package pkg : pkgs) {
1634                 String pkgName = pkg.getName();
1635                 if (!map.containsKey(pkgName)) {
1636                     map.put(pkgName, pkg);
1637                 }
1638             }
1639         }
1640         return map.values().toArray(new Package[map.size()]);
1641     }
1642 
1643 
1644     // -- Native library access --
1645 
1646     /**
1647      * Returns the absolute path name of a native library.  The VM invokes this
1648      * method to locate the native libraries that belong to classes loaded with
1649      * this class loader. If this method returns <tt>null</tt>, the VM
1650      * searches the library along the path specified as the
1651      * "<tt>java.library.path</tt>" property.
1652      *
1653      * @param  libname
1654      *         The library name
1655      *