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

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

@@ -27,16 +27,14 @@
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.AccessControlContext;
 import java.security.CodeSource;
-import java.security.Policy;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;

@@ -52,11 +50,10 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import sun.misc.CompoundEnumeration;
 import sun.misc.Resource;
 import sun.misc.URLClassPath;
-import sun.misc.VM;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.util.SecurityConstants;
 

@@ -266,12 +263,12 @@
         classes.addElement(c);
     }
 
     // The packages defined in this class loader.  Each package name is mapped
     // to its corresponding Package object.
-    // @GuardedBy("itself")
-    private final HashMap<String, Package> packages = new HashMap<>();
+    private final ConcurrentHashMap<String, Package> packages
+            = new ConcurrentHashMap<>();
 
     private static Void checkCreateClassLoader() {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkCreateClassLoader();

@@ -1573,21 +1570,21 @@
                                     String specVersion, String specVendor,
                                     String implTitle, String implVersion,
                                     String implVendor, URL sealBase)
         throws IllegalArgumentException
     {
-        synchronized (packages) {
             Package pkg = getPackage(name);
             if (pkg != null) {
                 throw new IllegalArgumentException(name);
             }
             pkg = new Package(name, specTitle, specVersion, specVendor,
                               implTitle, implVersion, implVendor,
                               sealBase, this);
-            packages.put(name, pkg);
-            return pkg;
+        if (packages.putIfAbsent(name, pkg) != null) {
+            throw new IllegalArgumentException(name);
         }
+        return pkg;
     }
 
     /**
      * Returns a <tt>Package</tt> that has been defined by this class loader
      * or any of its ancestors.

@@ -1599,30 +1596,17 @@
      *          <tt>null</tt> if not found
      *
      * @since  1.2
      */
     protected Package getPackage(String name) {
-        Package pkg;
-        synchronized (packages) {
-            pkg = packages.get(name);
-        }
+        Package pkg = packages.get(name);
         if (pkg == null) {
             if (parent != null) {
                 pkg = parent.getPackage(name);
             } else {
                 pkg = Package.getSystemPackage(name);
             }
-            if (pkg != null) {
-                synchronized (packages) {
-                    Package pkg2 = packages.get(name);
-                    if (pkg2 == null) {
-                        packages.put(name, pkg);
-                    } else {
-                        pkg = pkg2;
-                    }
-                }
-            }
         }
         return pkg;
     }
 
     /**

@@ -1633,26 +1617,22 @@
      *          <tt>ClassLoader</tt>
      *
      * @since  1.2
      */
     protected Package[] getPackages() {
-        Map<String, Package> map;
-        synchronized (packages) {
-            map = new HashMap<>(packages);
-        }
         Package[] pkgs;
         if (parent != null) {
             pkgs = parent.getPackages();
         } else {
             pkgs = Package.getSystemPackages();
         }
+
+        Map<String, Package> map = packages;
         if (pkgs != null) {
+            map = new HashMap<>(packages);
             for (Package pkg : pkgs) {
-                String pkgName = pkg.getName();
-                if (map.get(pkgName) == null) {
-                    map.put(pkgName, pkg);
-                }
+                map.putIfAbsent(pkg.getName(), pkg);
             }
         }
         return map.values().toArray(new Package[map.size()]);
     }