说明:此篇文章第一部分内容不够完善,请直接阅读第二部分。主要思路是对类加载器的执行过程做个总结,让读者能够对执行过程有个清晰明了的认识。
在进行ClassLoader类加载器实现细节分析之前,我们先对用到的几个类进行分析。
1、Guard接口,提供checkGuard(Object)方法,用于判定对象是否可被访问
public interface Guard {
//判断对象是否可以被访问,如果不能被访问则抛异常
void checkGuard(Object object) throws SecurityException;
}
2、Permission权限对象,有自己的名称,检查是否有对指定对象的访问权限,是否包含其他权限对象。
package java.security;
public abstract class Permission implements Guard, java.io.Serializable {
private String name;
public Permission(String name) {
this.name = name;
}
@Override //是否有权限访问object对象
public void checkGuard(Object object) throws SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(this);
}
//是否有包含permission权限
public abstract boolean implies(Permission permission);
public abstract boolean equals(Object obj);
public abstract int hashCode();
public final String getName() {
return name;
}
//获取所有?的字符串格式
public abstract String getActions();
//返回null
public PermissionCollection newPermissionCollection() {
return null;
}
public String toString() {
String actions = getActions();
if ((actions == null) || (actions.length() == 0)) { // OPTIONAL
return "(\"" + getClass().getName() + "\" \"" + name + "\")";
} else {
return "(\"" + getClass().getName() + "\" \"" + name +
"\" \"" + actions + "\")";
}
}
}
3、PermissionCollection是Permission对象的集合类对象,里面封装有一个集合用于管理Permission对象。
package java.security;
import java.util.*;
public abstract class PermissionCollection implements java.io.Serializable {
private volatile boolean readOnly;
//保存Permission对象的集合对象
public abstract Enumeration elements();
//添加权限
public abstract void add(Permission permission);
//是否包含权限
public abstract boolean implies(Permission permission);
//设置为只读集合对象,之后就不能再添加Permission对象
public void setReadOnly() {
readOnly = true;
}
public boolean isReadOnly() {
return readOnly;
}
public String toString() {
Enumeration enum_ = elements();
StringBuilder sb = new StringBuilder();
sb.append(super.toString()+" (\n");
while (enum_.hasMoreElements()) {
try {
sb.append(" ");
sb.append(enum_.nextElement().toString());
sb.append("\n");
} catch (NoSuchElementException e){
// ignore
}
}
sb.append(")\n");
return sb.toString();
}
}
4、CodeSource类,对应Class文件的路径,签名数组,证书数组。
public class CodeSource implements java.io.Serializable {
//代码文件的路径
private URL location;
//开发者签名对象数组
private transient CodeSigner[] signers = null;
//证书对象数组
private transient java.security.cert.Certificate certs[] = null;
// used for matchLocation
private transient SocketPermission sp;
// for generating cert paths
private transient CertificateFactory factory = null;
public CodeSource(URL url, java.security.cert.Certificate certs[]) {
this.location = url;
// Copy the supplied certs
if (certs != null) {
this.certs = certs.clone();
}
}
public CodeSource(URL url, CodeSigner[] signers) {
this.location = url;
// Copy the supplied signers
if (signers != null) {
this.signers = signers.clone();
}
}
5、ProtectionDomain类,包含了拥有一组权限的class的集合,当该类的对象创建的时候就会被赋予一些权限Permisson,当然也可以在对象构建的时候被动态赋予一些权限。
package java.security;
public class ProtectionDomain {
private static class JavaSecurityAccessImpl implements JavaSecurityAccess {
private JavaSecurityAccessImpl() {
}
@Override //交叉授权
public T doIntersectionPrivilege(
PrivilegedAction action,
final AccessControlContext stack,
final AccessControlContext context) {
if (action == null) {
throw new NullPointerException();
}
return AccessController.doPrivileged(
action,
getCombinedACC(context, stack)
);
}
@Override
public T doIntersectionPrivilege(
PrivilegedAction action,
AccessControlContext context) {
return doIntersectionPrivilege(action,
AccessController.getContext(), context);
}
//获取合并后的AccessControlContext对象
private static AccessControlContext getCombinedACC(AccessControlContext context, AccessControlContext stack) {
AccessControlContext acc = new AccessControlContext(context, stack.getCombiner(), true);
return new AccessControlContext(stack.getContext(), acc).optimize();
}
}
static {
// Set up JavaSecurityAccess in SharedSecrets
SharedSecrets.setJavaSecurityAccess(new JavaSecurityAccessImpl());
}
private CodeSource codesource ;
//来自于受保护域的classLoader
private ClassLoader classloader;
//主角数组(主角可以是一个公司,登录id,或者个体)
private Principal[] principals;
private PermissionCollection permissions;
//是否具有所有权限(最高权限)
private boolean hasAllPerm = false;
//权限对象是否是静态的(静态赋予Permissions)
private boolean staticPermissions;
// Key是静态最终的内部类:static final class Key {}
final Key key = new Key();
private static final Debug debug = Debug.getInstance("domain");
//传入并保存code source对象和permissions对象,staticPermissions 属性设置为true,如果permissions不为null,则设置为只读。
public ProtectionDomain(CodeSource codesource,
PermissionCollection permissions) {
this.codesource = codesource;
if (permissions != null) {
this.permissions = permissions;
this.permissions.setReadOnly();
if (permissions instanceof Permissions &&
((Permissions)permissions).allPermission != null) {
hasAllPerm = true;
}
}
this.classloader = null;
this.principals = new Principal[0];
staticPermissions = true;
}
public ProtectionDomain(CodeSource codesource,
PermissionCollection permissions,
ClassLoader classloader,
Principal[] principals) {
this.codesource = codesource;
if (permissions != null) {
this.permissions = permissions;
this.permissions.setReadOnly();
if (permissions instanceof Permissions &&
((Permissions)permissions).allPermission != null) {
hasAllPerm = true;
}
}
this.classloader = classloader;
this.principals = (principals != null ? principals.clone():
new Principal[0]);
staticPermissions = false;
}
public final CodeSource getCodeSource() {
return this.codesource;
}
public final ClassLoader getClassLoader() {
return this.classloader;
}
public final Principal[] getPrincipals() {
return this.principals.clone();
}
public final PermissionCollection getPermissions() {
return permissions;
}
public boolean implies(Permission permission) {
if (hasAllPerm) {
return true;
}
if (!staticPermissions &&
Policy.getPolicyNoCheck().implies(this, permission))
return true;
if (permissions != null)
return permissions.implies(permission);
return false;
}
boolean impliesCreateAccessControlContext() {
return implies(SecurityConstants.CREATE_ACC_PERMISSION);
}
@Override public String toString() {
String pals = "" ;
if (principals != null && principals.length > 0) {
StringBuilder palBuf = new StringBuilder("(principals ");
for (int i = 0; i < principals.length; i++) {
palBuf.append(principals[i].getClass().getName() +
" \"" + principals[i].getName() +
"\"");
if (i < principals.length-1)
palBuf.append(",\n");
else
palBuf.append(")\n");
}
pals = palBuf.toString();
}
return "ProtectionDomain "+
" "+codesource+"\n"+
" "+classloader+"\n"+
" "+pals+"\n"+
" "+pc+"\n";
}
private static boolean seeAllp() {
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
return true;
} else {
if (debug != null) {
if (sm.getClass().getClassLoader() == null &&
Policy.getPolicyNoCheck().getClass().getClassLoader()
== null) {
return true;
}
} else {
try {
sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
return true;
} catch (SecurityException se) {
// fall thru and return false
}
}
}
return false;
}
private PermissionCollection mergePermissions() {
if (staticPermissions)
return permissions;
PermissionCollection perms =
java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction() {
public PermissionCollection run() {
Policy p = Policy.getPolicyNoCheck();
return p.getPermissions(ProtectionDomain.this);
}
});
Permissions mergedPerms = new Permissions();
int swag = 32;
int vcap = 8;
Enumeration e;
List pdVector = new ArrayList<>(vcap);
List plVector = new ArrayList<>(swag);
//
// Build a vector of domain permissions for subsequent merge
if (permissions != null) {
synchronized (permissions) {
e = permissions.elements();
while (e.hasMoreElements()) {
pdVector.add(e.nextElement());
}
}
}
//
// Build a vector of Policy permissions for subsequent merge
if (perms != null) {
synchronized (perms) {
e = perms.elements();
while (e.hasMoreElements()) {
plVector.add(e.nextElement());
vcap++;
}
}
}
if (perms != null && permissions != null) {
//
// Weed out the duplicates from the policy. Unless a refresh
// has occurred since the pd was consed this should result in
// an empty vector.
synchronized (permissions) {
e = permissions.elements(); // domain vs policy
while (e.hasMoreElements()) {
Permission pdp = e.nextElement();
Class> pdpClass = pdp.getClass();
String pdpActions = pdp.getActions();
String pdpName = pdp.getName();
for (int i = 0; i < plVector.size(); i++) {
Permission pp = plVector.get(i);
if (pdpClass.isInstance(pp)) {
// The equals() method on some permissions
// have some side effects so this manual
// comparison is sufficient.
if (pdpName.equals(pp.getName()) &&
pdpActions.equals(pp.getActions())) {
plVector.remove(i);
break;
}
}
}
}
}
}
if (perms !=null) {
// the order of adding to merged perms and permissions
// needs to preserve the bugfix 4301064
for (int i = plVector.size()-1; i >= 0; i--) {
mergedPerms.add(plVector.get(i));
}
}
if (permissions != null) {
for (int i = pdVector.size()-1; i >= 0; i--) {
mergedPerms.add(pdVector.get(i));
}
}
return mergedPerms;
}
/**
* Used for storing ProtectionDomains as keys in a Map.
*/
static final class Key {}
static {
SharedSecrets.setJavaSecurityProtectionDomainAccess(
new JavaSecurityProtectionDomainAccess() {
@Override
public ProtectionDomainCache getProtectionDomainCache() {
return new PDCache();
}
@Override
public boolean getStaticPermissionsField(ProtectionDomain pd) {
return pd.staticPermissions;
}
});
}
private static class PDCache implements ProtectionDomainCache {
private final ConcurrentHashMap>
pdMap = new ConcurrentHashMap<>();
private final ReferenceQueue queue = new ReferenceQueue<>();
@Override
public void put(ProtectionDomain pd, PermissionCollection pc) {
processQueue(queue, pdMap);
WeakProtectionDomainKey weakPd =
new WeakProtectionDomainKey(pd, queue);
pdMap.put(weakPd, new SoftReference<>(pc));
}
@Override
public PermissionCollection get(ProtectionDomain pd) {
processQueue(queue, pdMap);
WeakProtectionDomainKey weakPd = new WeakProtectionDomainKey(pd);
SoftReference sr = pdMap.get(weakPd);
return (sr == null) ? null : sr.get();
}
private static void processQueue(ReferenceQueue queue,
ConcurrentHashMap extends
WeakReference, ?> pdMap) {
Reference extends Key> ref;
while ((ref = queue.poll()) != null) {
pdMap.remove(ref);
}
}
}
private static class WeakProtectionDomainKey extends WeakReference {
private final int hash;
private static final Key NULL_KEY = new Key();
WeakProtectionDomainKey(ProtectionDomain pd, ReferenceQueue rq) {
this((pd == null ? NULL_KEY : pd.key), rq);
}
WeakProtectionDomainKey(ProtectionDomain pd) {
this(pd == null ? NULL_KEY : pd.key);
}
private WeakProtectionDomainKey(Key key, ReferenceQueue rq) {
super(key, rq);
hash = key.hashCode();
}
private WeakProtectionDomainKey(Key key) {
super(key);
hash = key.hashCode();
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof WeakProtectionDomainKey) {
Object referent = get();
return (referent != null) &&
(referent == ((WeakProtectionDomainKey)obj).get());
} else {
return false;
}
}
}
}
6、DomainCombiner类,用于合并ProtectionDomain对象数组。
ProtectionDomain[] combine(ProtectionDomain[] currentDomains,ProtectionDomain[] assignedDomains);
7、AccessControlContext 访问控制上下文,核心类
package java.security;
import java.util.ArrayList;
import java.util.List;
import sun.security.util.Debug;
import sun.security.util.SecurityConstants;
public final class AccessControlContext {
private ProtectionDomain context[];
// isPrivileged and isAuthorized are referenced by the VM - do not remove
// or change their names 虚拟机私有
private boolean isPrivileged;
private boolean isAuthorized = false;
// Note: This field is directly used by the virtual machine
// native codes. Don't touch it. 虚拟机私有
private AccessControlContext privilegedContext;
private DomainCombiner combiner = null;
// limited privilege scope 有限的权限数组
private Permission permissions[];
//
private AccessControlContext parent;
private boolean isWrapped;//是否已经绑定
// is constrained by limited privilege scope?
private boolean isLimited;
private ProtectionDomain limitedContext[];
//初始化时调试
private static boolean debugInit = false;
private static Debug debug = null;
static Debug getDebug()
{
if (debugInit)
return debug;
else {
if (Policy.isSet()) {
debug = Debug.getInstance("access");
debugInit = true;
}
return debug;
}
}
// 根据ProtectionDomain数组初始化成员变量context数组
public AccessControlContext(ProtectionDomain context[])
{
if (context.length == 0) {
this.context = null;
} else if (context.length == 1) {
if (context[0] != null) {
this.context = context.clone();
} else {
this.context = null;
}
} else {
List v = new ArrayList<>(context.length);
for (int i =0; i< context.length; i++) {
if ((context[i] != null) && (!v.contains(context[i])))
v.add(context[i]);
}
if (!v.isEmpty()) {
this.context = new ProtectionDomain[v.size()];
this.context = v.toArray(this.context);
}
}
}
// 公共构造器
public AccessControlContext(AccessControlContext acc,
DomainCombiner combiner) {
this(acc, combiner, false);
}
// 非公共构造器
AccessControlContext(AccessControlContext acc,
DomainCombiner combiner,
boolean preauthorized) {
// 没有预授权则先授权
if (!preauthorized) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION);
this.isAuthorized = true;
}
} else {
this.isAuthorized = true;
}
// 直接初始化成员变量context数组
this.context = acc.context;
// 初始化ProtectionDomain数组的合并器
this.combiner = combiner;
}
// 非公共构造器
AccessControlContext(ProtectionDomain caller, DomainCombiner combiner,
AccessControlContext parent, AccessControlContext context,
Permission[] perms)
{
ProtectionDomain[] callerPDs = null;
if (caller != null) {
callerPDs = new ProtectionDomain[] { caller };
}
// 合并context数组
if (context != null) {
if (combiner != null) {
this.context = combiner.combine(callerPDs, context.context);
} else {
this.context = combine(callerPDs, context.context);
}
} else {
if (combiner != null) {
this.context = combiner.combine(callerPDs, null);
} else {
this.context = combine(callerPDs, null);
}
}
this.combiner = combiner;
Permission[] tmp = null;
if (perms != null) {
tmp = new Permission[perms.length];
for (int i=0; i < perms.length; i++) {
if (perms[i] == null) {
throw new NullPointerException("permission can't be null");
}
if (perms[i].getClass() == AllPermission.class) {
parent = null;
}
tmp[i] = perms[i];
}
}
//如果有parent,则将parent的权限继承自子类中(当前对象)
if (parent != null) {
this.limitedContext = combine(parent.context, parent.limitedContext);
this.isLimited = true;
this.isWrapped = true;
this.permissions = tmp;
this.parent = parent;
this.privilegedContext = context; // used in checkPermission2()
}
this.isAuthorized = true;
}
AccessControlContext(ProtectionDomain context[],
boolean isPrivileged)
{
this.context = context;
this.isPrivileged = isPrivileged;
this.isAuthorized = true;
}
//Constructor for JavaSecurityAccess.doIntersectionPrivilege()
AccessControlContext(ProtectionDomain[] context,
AccessControlContext privilegedContext)
{
this.context = context;
this.privilegedContext = privilegedContext;
this.isPrivileged = true;
}
ProtectionDomain[] getContext() {
return context;
}
boolean isPrivileged()
{
return isPrivileged;
}
/**
* get the assigned combiner from the privileged or inherited context
*/
DomainCombiner getAssignedCombiner() {
AccessControlContext acc;
if (isPrivileged) {
acc = privilegedContext;
} else {
acc = AccessController.getInheritedAccessControlContext();
}
if (acc != null) {
return acc.combiner;
}
return null;
}
public DomainCombiner getDomainCombiner() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.GET_COMBINER_PERMISSION);
}
return getCombiner();
}
// 非公有的方法
DomainCombiner getCombiner() {
return combiner;
}
boolean isAuthorized() {
return isAuthorized;
}
/**
* Determines whether the access request indicated by the
* specified permission should be allowed or denied, based on
* the security policy currently in effect, and the context in
* this object. The request is allowed only if every ProtectionDomain
* in the context implies the permission. Otherwise the request is
* denied.
public void checkPermission(Permission perm)
throws AccessControlException
{
boolean dumpDebug = false;
if (perm == null) {
throw new NullPointerException("permission can't be null");
}
if (getDebug() != null) {
dumpDebug = !Debug.isOn("codebase=");
if (!dumpDebug) {
for (int i = 0; context != null && i < context.length; i++) {
if (context[i].getCodeSource() != null &&
context[i].getCodeSource().getLocation() != null &&
Debug.isOn("codebase=" + context[i].getCodeSource().getLocation().toString())) {
dumpDebug = true;
break;
}
}
}
dumpDebug &= !Debug.isOn("permission=") ||
Debug.isOn("permission=" + perm.getClass().getCanonicalName());
if (dumpDebug && Debug.isOn("stack")) {
Thread.dumpStack();
}
if (dumpDebug && Debug.isOn("domain")) {
if (context == null) {
debug.println("domain (context is null)");
} else {
for (int i=0; i< context.length; i++) {
debug.println("domain "+i+" "+context[i]);
}
}
}
}
if (context == null) {
checkPermission2(perm);
return;
}
for (int i=0; i< context.length; i++) {
if (context[i] != null && !context[i].implies(perm)) {
if (dumpDebug) {
debug.println("access denied " + perm);
}
if (Debug.isOn("failure") && debug != null) {
if (!dumpDebug) {
debug.println("access denied " + perm);
}
Thread.dumpStack();
final ProtectionDomain pd = context[i];
final Debug db = debug;
AccessController.doPrivileged (new PrivilegedAction() {
public Void run() {
db.println("domain that failed "+pd);
return null;
}
});
}
throw new AccessControlException("access denied "+perm, perm);
}
}
// allow if all of them allowed access
if (dumpDebug) {
debug.println("access allowed "+perm);
}
checkPermission2(perm);
}
//检查与有限权限范围相关联的域
private void checkPermission2(Permission perm) {
if (!isLimited) {
// 如果没有限制,则不用检查
return;
}
// 检查权限范围
if (privilegedContext != null) {
privilegedContext.checkPermission2(perm);
}
// 如果已经被包含,则不用检查
if (isWrapped) {
return;
}
// 检查所有限制的权限
if (permissions != null) {
Class> permClass = perm.getClass();
for (int i=0; i < permissions.length; i++) {
Permission limit = permissions[i];
if (limit.getClass().equals(permClass) && limit.implies(perm)) {
return;
}
}
}
if (parent != null) {
if (permissions == null) {
parent.checkPermission2(perm);
} else {
parent.checkPermission(perm);
}
}
}
//优化处理
AccessControlContext optimize() {
// the assigned (privileged or inherited) context
AccessControlContext acc;
DomainCombiner combiner = null;
AccessControlContext parent = null;
Permission[] permissions = null;
if (isPrivileged) {
acc = privilegedContext;
if (acc != null) {
if (acc.isWrapped) {
permissions = acc.permissions;
parent = acc.parent;
}
}
} else {
acc = AccessController.getInheritedAccessControlContext();
if (acc != null) {
if (acc.isLimited) {
parent = acc;
}
}
}
boolean skipStack = (context == null);
boolean skipAssigned = (acc == null || acc.context == null);
ProtectionDomain[] assigned = (skipAssigned) ? null : acc.context;
ProtectionDomain[] pd;
boolean skipLimited = ((acc == null || !acc.isWrapped) && parent == null);
if (acc != null && acc.combiner != null) {
if (getDebug() != null) {
debug.println("AccessControlContext invoking the Combiner");
}
combiner = acc.combiner;
pd = combiner.combine(context, assigned);
} else {
if (skipStack) {
if (skipAssigned) {
calculateFields(acc, parent, permissions);
return this;
} else if (skipLimited) {
return acc;
}
} else if (assigned != null) {
if (skipLimited) {
if (context.length == 1 && context[0] == assigned[0]) {
return acc;
}
}
}
pd = combine(context, assigned);
if (skipLimited && !skipAssigned && pd == assigned) {
return acc;
} else if (skipAssigned && pd == context) {
calculateFields(acc, parent, permissions);
return this;
}
}
this.context = pd;
this.combiner = combiner;
this.isPrivileged = false;
calculateFields(acc, parent, permissions);
return this;
}
private static ProtectionDomain[] combine(ProtectionDomain[]current,
ProtectionDomain[] assigned) {
boolean skipStack = (current == null);
boolean skipAssigned = (assigned == null);
int slen = (skipStack) ? 0 : current.length;
if (skipAssigned && slen <= 2) {
return current;
}
int n = (skipAssigned) ? 0 : assigned.length;
ProtectionDomain pd[] = new ProtectionDomain[slen + n];
// first copy in the assigned context domains, no need to compress
if (!skipAssigned) {
System.arraycopy(assigned, 0, pd, 0, n);
}
// now add the stack context domains, discarding nulls and duplicates
outer:
for (int i = 0; i < slen; i++) {
ProtectionDomain sd = current[i];
if (sd != null) {
for (int j = 0; j < n; j++) {
if (sd == pd[j]) {
continue outer;
}
}
pd[n++] = sd;
}
}
// if length isn't equal, we need to shorten the array
if (n != pd.length) {
// optimization: if we didn't really combine anything
if (!skipAssigned && n == assigned.length) {
return assigned;
} else if (skipAssigned && n == slen) {
return current;
}
ProtectionDomain tmp[] = new ProtectionDomain[n];
System.arraycopy(pd, 0, tmp, 0, n);
pd = tmp;
}
return pd;
}
private void calculateFields(AccessControlContext assigned,
AccessControlContext parent, Permission[] permissions)
{
ProtectionDomain[] parentLimit = null;
ProtectionDomain[] assignedLimit = null;
ProtectionDomain[] newLimit;
parentLimit = (parent != null)? parent.limitedContext: null;
assignedLimit = (assigned != null)? assigned.limitedContext: null;
newLimit = combine(parentLimit, assignedLimit);
if (newLimit != null) {
if (context == null || !containsAllPDs(newLimit, context)) {
this.limitedContext = newLimit;
this.permissions = permissions;
this.parent = parent;
this.isLimited = true;
}
}
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (! (obj instanceof AccessControlContext))
return false;
AccessControlContext that = (AccessControlContext) obj;
if (!equalContext(that))
return false;
if (!equalLimitedContext(that))
return false;
return true;
}
private boolean equalContext(AccessControlContext that) {
if (!equalPDs(this.context, that.context))
return false;
if (this.combiner == null && that.combiner != null)
return false;
if (this.combiner != null && !this.combiner.equals(that.combiner))
return false;
return true;
}
private boolean equalPDs(ProtectionDomain[] a, ProtectionDomain[] b) {
if (a == null) {
return (b == null);
}
if (b == null)
return false;
if (!(containsAllPDs(a, b) && containsAllPDs(b, a)))
return false;
return true;
}
private boolean equalLimitedContext(AccessControlContext that) {
if (that == null)
return false;
if (!this.isLimited && !that.isLimited)
return true;
if (!(this.isLimited && that.isLimited))
return false;
if ((this.isWrapped && !that.isWrapped) ||
(!this.isWrapped && that.isWrapped)) {
return false;
}
if (this.permissions == null && that.permissions != null)
return false;
if (this.permissions != null && that.permissions == null)
return false;
if (!(this.containsAllLimits(that) && that.containsAllLimits(this)))
return false;
AccessControlContext thisNextPC = getNextPC(this);
AccessControlContext thatNextPC = getNextPC(that);
if (thisNextPC == null && thatNextPC != null && thatNextPC.isLimited)
return false;
if (thisNextPC != null && !thisNextPC.equalLimitedContext(thatNextPC))
return false;
if (this.parent == null && that.parent != null)
return false;
if (this.parent != null && !this.parent.equals(that.parent))
return false;
return true;
}
private static AccessControlContext getNextPC(AccessControlContext acc) {
while (acc != null && acc.privilegedContext != null) {
acc = acc.privilegedContext;
if (!acc.isWrapped)
return acc;
}
return null;
}
private static boolean containsAllPDs(ProtectionDomain[] thisContext,
ProtectionDomain[] thatContext) {
boolean match = false;
ProtectionDomain thisPd;
for (int i = 0; i < thisContext.length; i++) {
match = false;
if ((thisPd = thisContext[i]) == null) {
for (int j = 0; (j < thatContext.length) && !match; j++) {
match = (thatContext[j] == null);
}
} else {
Class> thisPdClass = thisPd.getClass();
ProtectionDomain thatPd;
for (int j = 0; (j < thatContext.length) && !match; j++) {
thatPd = thatContext[j];
// Class check required to avoid PD exposure (4285406)
match = (thatPd != null &&
thisPdClass == thatPd.getClass() && thisPd.equals(thatPd));
}
}
if (!match) return false;
}
return match;
}
private boolean containsAllLimits(AccessControlContext that) {
boolean match = false;
Permission thisPerm;
if (this.permissions == null && that.permissions == null)
return true;
for (int i = 0; i < this.permissions.length; i++) {
Permission limit = this.permissions[i];
Class > limitClass = limit.getClass();
match = false;
for (int j = 0; (j < that.permissions.length) && !match; j++) {
Permission perm = that.permissions[j];
match = (limitClass.equals(perm.getClass()) &&
limit.equals(perm));
}
if (!match) return false;
}
return match;
}
public int hashCode() {
int hashCode = 0;
if (context == null)
return hashCode;
for (int i =0; i < context.length; i++) {
if (context[i] != null)
hashCode ^= context[i].hashCode();
}
return hashCode;
}
}
8、AccessControl类,访问控制类,不允许外界实例化对象。doPrivileged方法,该方法传入PrivilegedAction
类型的对象,依据权限相关模型,创建并返回泛型T对应的对象。
package java.security;
import sun.security.util.Debug;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
// 用于访问控制操作和决定,以及根据安全策略决定是否允许访问系统关键部位的资源,
public final class AccessController {
// 不允许外界实例化
private AccessController() { }
@CallerSensitive
public static native T doPrivileged(PrivilegedAction action);
@CallerSensitive
public static T doPrivilegedWithCombiner(PrivilegedAction action) {
AccessControlContext acc = getStackAccessControlContext();
if (acc == null) {
return AccessController.doPrivileged(action);
}
DomainCombiner dc = acc.getAssignedCombiner();
return AccessController.doPrivileged(action,
preserveCombiner(dc, Reflection.getCallerClass()));
}
@CallerSensitive
public static native T doPrivileged(PrivilegedAction action,
AccessControlContext context);
@CallerSensitive
public static T doPrivileged(PrivilegedAction action,
AccessControlContext context, Permission... perms) {
AccessControlContext parent = getContext();
if (perms == null) {
throw new NullPointerException("null permissions parameter");
}
Class > caller = Reflection.getCallerClass();
return AccessController.doPrivileged(action, createWrapper(null,
caller, parent, context, perms));
}
@CallerSensitive
public static T doPrivilegedWithCombiner(PrivilegedAction action,
AccessControlContext context, Permission... perms) {
AccessControlContext parent = getContext();
DomainCombiner dc = parent.getCombiner();
if (dc == null && context != null) {
dc = context.getCombiner();
}
if (perms == null) {
throw new NullPointerException("null permissions parameter");
}
Class > caller = Reflection.getCallerClass();
return AccessController.doPrivileged(action, createWrapper(dc, caller,
parent, context, perms));
}
@CallerSensitive
public static native T
doPrivileged(PrivilegedExceptionAction action)
throws PrivilegedActionException;
@CallerSensitive
public static T doPrivilegedWithCombiner(PrivilegedExceptionAction action)
throws PrivilegedActionException
{
AccessControlContext acc = getStackAccessControlContext();
if (acc == null) {
return AccessController.doPrivileged(action);
}
DomainCombiner dc = acc.getAssignedCombiner();
return AccessController.doPrivileged(action,
preserveCombiner(dc, Reflection.getCallerClass()));
}
private static AccessControlContext preserveCombiner(DomainCombiner combiner,
Class> caller)
{
return createWrapper(combiner, caller, null, null, null);
}
private static AccessControlContext
createWrapper(DomainCombiner combiner, Class> caller,
AccessControlContext parent, AccessControlContext context,
Permission[] perms)
{
ProtectionDomain callerPD = getCallerPD(caller);
// check if caller is authorized to create context
if (context != null && !context.isAuthorized() &&
System.getSecurityManager() != null &&
!callerPD.impliesCreateAccessControlContext())
{
ProtectionDomain nullPD = new ProtectionDomain(null, null);
return new AccessControlContext(new ProtectionDomain[] { nullPD });
} else {
return new AccessControlContext(callerPD, combiner, parent,
context, perms);
}
}
private static ProtectionDomain getCallerPD(final Class > caller) {
ProtectionDomain callerPd = doPrivileged
(new PrivilegedAction() {
public ProtectionDomain run() {
return caller.getProtectionDomain();
}
});
return callerPd;
}
@CallerSensitive
public static native T
doPrivileged(PrivilegedExceptionAction action,
AccessControlContext context)
throws PrivilegedActionException;
@CallerSensitive
public static T doPrivileged(PrivilegedExceptionAction action,
AccessControlContext context, Permission... perms)
throws PrivilegedActionException
{
AccessControlContext parent = getContext();
if (perms == null) {
throw new NullPointerException("null permissions parameter");
}
Class > caller = Reflection.getCallerClass();
return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms));
}
@CallerSensitive
public static T doPrivilegedWithCombiner(PrivilegedExceptionAction action,
AccessControlContext context,
Permission... perms)
throws PrivilegedActionException
{
AccessControlContext parent = getContext();
DomainCombiner dc = parent.getCombiner();
if (dc == null && context != null) {
dc = context.getCombiner();
}
if (perms == null) {
throw new NullPointerException("null permissions parameter");
}
Class > caller = Reflection.getCallerClass();
return AccessController.doPrivileged(action, createWrapper(dc, caller,
parent, context, perms));
}
private static native AccessControlContext getStackAccessControlContext();
static native AccessControlContext getInheritedAccessControlContext();
public static AccessControlContext getContext()
{
AccessControlContext acc = getStackAccessControlContext();
if (acc == null) {
// all we had was privileged system code. We don't want
// to return null though, so we construct a real ACC.
return new AccessControlContext(null, true);
} else {
return acc.optimize();
}
}
public static void checkPermission(Permission perm)
throws AccessControlException
{
//System.err.println("checkPermission "+perm);
//Thread.currentThread().dumpStack();
if (perm == null) {
throw new NullPointerException("permission can't be null");
}
AccessControlContext stack = getStackAccessControlContext();
// if context is null, we had privileged system code on the stack.
if (stack == null) {
Debug debug = AccessControlContext.getDebug();
boolean dumpDebug = false;
if (debug != null) {
dumpDebug = !Debug.isOn("codebase=");
dumpDebug &= !Debug.isOn("permission=") ||
Debug.isOn("permission=" + perm.getClass().getCanonicalName());
}
if (dumpDebug && Debug.isOn("stack")) {
Thread.dumpStack();
}
if (dumpDebug && Debug.isOn("domain")) {
debug.println("domain (context is null)");
}
if (dumpDebug) {
debug.println("access allowed "+perm);
}
return;
}
AccessControlContext acc = stack.optimize();
acc.checkPermission(perm);
}
}
加载过程是由类加载器负责执行的,具体实现过程为,先创建类加载器对象,然后调用它的loadClass(String)方法,在loadClass方法中先调用findLoadedClass(String)方法以检查该类是否已经被加载过,如果已经加载则直接返回被加载的Class对象;如果没有加载,则调用父类加载器对象的loadClass(String)方法来加载该类,依次递归,直到将加载请求发送给BootStrap类加载器,Bootstrap类加载器拥有加载类的优先权,对于符合其加载路径的class文件都将会由Bootstrap加载进JVM。否则将加载的任务交给子类加载器,依次递归。当所有的父类加载器都不能完成加载指定的类文件时,将由当前类加载器来直接加载。加载的直接结果就是返回指定类对应的字节码对象。