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
@@ -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;
@@ -267,11 +264,12 @@
}
// 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 +1571,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;
- }
+ // Races here can be safely dealt with by ensuring we always return
+ // the same package object
+ Package oldPkg = packages.putIfAbsent(name, pkg);
+ return (oldPkg != null ? oldPkg : pkg);
}
/**
* Returns a <tt>Package</tt> that has been defined by this class loader
* or any of its ancestors.
@@ -1599,30 +1597,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;
}
/**
@@ -1634,28 +1619,30 @@
*
* @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();
}
- if (pkgs != null) {
+
+ if (pkgs == null) {
+ map = packages;
+ } else {
+ map = new HashMap<>(packages);
for (Package pkg : pkgs) {
String pkgName = pkg.getName();
- if (map.get(pkgName) == null) {
+ if (!map.containsKey(pkgName)) {
map.put(pkgName, pkg);
}
}
}
return map.values().toArray(new Package[map.size()]);
+
}
// -- Native library access --