提交 56291cd2 编写于 作者: M mullan

7093090: Reduce synchronization in java.security.Policy.getPolicyNoCheck

Reviewed-by: valeriep
上级 fa4eae9d
...@@ -28,6 +28,7 @@ package java.security; ...@@ -28,6 +28,7 @@ package java.security;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicReference;
import sun.security.jca.GetInstance; import sun.security.jca.GetInstance;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -60,8 +61,8 @@ import sun.security.util.SecurityConstants; ...@@ -60,8 +61,8 @@ import sun.security.util.SecurityConstants;
* with a standard type. The default policy type is "JavaPolicy". * with a standard type. The default policy type is "JavaPolicy".
* *
* <p> Once a Policy instance has been installed (either by default, or by * <p> Once a Policy instance has been installed (either by default, or by
* calling <code>setPolicy</code>), * calling <code>setPolicy</code>), the Java runtime invokes its
* the Java runtime invokes its <code>implies</code> when it needs to * <code>implies</code> method when it needs to
* determine whether executing code (encapsulated in a ProtectionDomain) * determine whether executing code (encapsulated in a ProtectionDomain)
* can perform SecurityManager-protected operations. How a Policy object * can perform SecurityManager-protected operations. How a Policy object
* retrieves its policy data is up to the Policy implementation itself. * retrieves its policy data is up to the Policy implementation itself.
...@@ -94,18 +95,33 @@ public abstract class Policy { ...@@ -94,18 +95,33 @@ public abstract class Policy {
public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION = public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
new UnsupportedEmptyCollection(); new UnsupportedEmptyCollection();
/** the system-wide policy. */ // Information about the system-wide policy.
private static Policy policy; // package private for AccessControlContext private static class PolicyInfo {
// the system-wide policy
final Policy policy;
// a flag indicating if the system-wide policy has been initialized
final boolean initialized;
PolicyInfo(Policy policy, boolean initialized) {
this.policy = policy;
this.initialized = initialized;
}
}
// PolicyInfo is stored in an AtomicReference
private static AtomicReference<PolicyInfo> policy =
new AtomicReference<>(new PolicyInfo(null, false));
private static final Debug debug = Debug.getInstance("policy"); private static final Debug debug = Debug.getInstance("policy");
// Cache mapping ProtectionDomain.Key to PermissionCollection // Cache mapping ProtectionDomain.Key to PermissionCollection
private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping; private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
/** package private for AccessControlContext */ /** package private for AccessControlContext and ProtectionDomain */
static boolean isSet() static boolean isSet()
{ {
return policy != null; PolicyInfo pi = policy.get();
return pi.policy != null && pi.initialized == true;
} }
private static void checkPermission(String type) { private static void checkPermission(String type) {
...@@ -143,80 +159,92 @@ public abstract class Policy { ...@@ -143,80 +159,92 @@ public abstract class Policy {
/** /**
* Returns the installed Policy object, skipping the security check. * Returns the installed Policy object, skipping the security check.
* Used by SecureClassLoader and getPolicy. * Used by ProtectionDomain and getPolicy.
* *
* @return the installed Policy. * @return the installed Policy.
*
*/ */
static synchronized Policy getPolicyNoCheck() static Policy getPolicyNoCheck()
{ {
if (policy == null) { PolicyInfo pi = policy.get();
String policy_class = null; // Use double-check idiom to avoid locking if system-wide policy is
policy_class = AccessController.doPrivileged( // already initialized
new PrivilegedAction<String>() { if (pi.initialized == false || pi.policy == null) {
public String run() { synchronized (Policy.class) {
return Security.getProperty("policy.provider"); PolicyInfo pinfo = policy.get();
if (pinfo.policy == null) {
String policy_class = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return Security.getProperty("policy.provider");
}
});
if (policy_class == null) {
policy_class = "sun.security.provider.PolicyFile";
} }
});
if (policy_class == null) {
policy_class = "sun.security.provider.PolicyFile";
}
try { try {
policy = (Policy) pinfo = new PolicyInfo(
Class.forName(policy_class).newInstance(); (Policy) Class.forName(policy_class).newInstance(),
} catch (Exception e) { true);
/* } catch (Exception e) {
* The policy_class seems to be an extension /*
* so we have to bootstrap loading it via a policy * The policy_class seems to be an extension
* provider that is on the bootclasspath * so we have to bootstrap loading it via a policy
* If it loads then shift gears to using the configured * provider that is on the bootclasspath.
* provider. * If it loads then shift gears to using the configured
*/ * provider.
*/
// install the bootstrap provider to avoid recursion
policy = new sun.security.provider.PolicyFile(); // install the bootstrap provider to avoid recursion
Policy polFile = new sun.security.provider.PolicyFile();
final String pc = policy_class; pinfo = new PolicyInfo(polFile, false);
Policy p = AccessController.doPrivileged( policy.set(pinfo);
new PrivilegedAction<Policy>() {
public Policy run() { final String pc = policy_class;
try { Policy pol = AccessController.doPrivileged(
ClassLoader cl = new PrivilegedAction<Policy>() {
ClassLoader.getSystemClassLoader(); public Policy run() {
// we want the extension loader try {
ClassLoader extcl = null; ClassLoader cl =
while (cl != null) { ClassLoader.getSystemClassLoader();
extcl = cl; // we want the extension loader
cl = cl.getParent(); ClassLoader extcl = null;
} while (cl != null) {
return (extcl != null ? (Policy)Class.forName( extcl = cl;
pc, true, extcl).newInstance() : null); cl = cl.getParent();
} catch (Exception e) { }
if (debug != null) { return (extcl != null ? (Policy)Class.forName(
debug.println("policy provider " + pc, true, extcl).newInstance() : null);
pc + } catch (Exception e) {
" not available"); if (debug != null) {
e.printStackTrace(); debug.println("policy provider " +
pc +
" not available");
e.printStackTrace();
}
return null;
} }
return null;
} }
});
/*
* if it loaded install it as the policy provider. Otherwise
* continue to use the system default implementation
*/
if (pol != null) {
pinfo = new PolicyInfo(pol, true);
} else {
if (debug != null) {
debug.println("using sun.security.provider.PolicyFile");
}
pinfo = new PolicyInfo(polFile, true);
} }
});
/*
* if it loaded install it as the policy provider. Otherwise
* continue to use the system default implementation
*/
if (p != null) {
policy = p;
} else {
if (debug != null) {
debug.println("using sun.security.provider.PolicyFile");
} }
policy.set(pinfo);
} }
return pinfo.policy;
} }
} }
return policy; return pi.policy;
} }
/** /**
...@@ -245,7 +273,7 @@ public abstract class Policy { ...@@ -245,7 +273,7 @@ public abstract class Policy {
initPolicy(p); initPolicy(p);
} }
synchronized (Policy.class) { synchronized (Policy.class) {
Policy.policy = p; policy.set(new PolicyInfo(p, p != null));
} }
} }
...@@ -292,14 +320,14 @@ public abstract class Policy { ...@@ -292,14 +320,14 @@ public abstract class Policy {
PermissionCollection policyPerms = null; PermissionCollection policyPerms = null;
synchronized (p) { synchronized (p) {
if (p.pdMapping == null) { if (p.pdMapping == null) {
p.pdMapping = p.pdMapping = new WeakHashMap<>();
new WeakHashMap<ProtectionDomain.Key, PermissionCollection>();
} }
} }
if (policyDomain.getCodeSource() != null) { if (policyDomain.getCodeSource() != null) {
if (Policy.isSet()) { Policy pol = policy.get().policy;
policyPerms = policy.getPermissions(policyDomain); if (pol != null) {
policyPerms = pol.getPermissions(policyDomain);
} }
if (policyPerms == null) { // assume it has all if (policyPerms == null) { // assume it has all
...@@ -434,7 +462,7 @@ public abstract class Policy { ...@@ -434,7 +462,7 @@ public abstract class Policy {
type, type,
params); params);
} catch (NoSuchAlgorithmException nsae) { } catch (NoSuchAlgorithmException nsae) {
return handleException (nsae); return handleException(nsae);
} }
} }
...@@ -494,7 +522,7 @@ public abstract class Policy { ...@@ -494,7 +522,7 @@ public abstract class Policy {
type, type,
params); params);
} catch (NoSuchAlgorithmException nsae) { } catch (NoSuchAlgorithmException nsae) {
return handleException (nsae); return handleException(nsae);
} }
} }
...@@ -808,7 +836,7 @@ public abstract class Policy { ...@@ -808,7 +836,7 @@ public abstract class Policy {
* *
* @param permission the Permission object to compare. * @param permission the Permission object to compare.
* *
* @return true if "permission" is implied by the permissions in * @return true if "permission" is implied by the permissions in
* the collection, false if not. * the collection, false if not.
*/ */
@Override public boolean implies(Permission permission) { @Override public boolean implies(Permission permission) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册