ClassLoader类加载器的实现细节

说明:此篇文章第一部分内容不够完善,请直接阅读第二部分。主要思路是对类加载器的执行过程做个总结,让读者能够对执行过程有个清晰明了的认识。

第一部分 权限访问相关类介绍


在进行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, ?> pdMap) {
            Reference 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);
    }
}

第二部分 通过分析Launcher和ClassLoader类,以明确类的加载过程


加载过程是由类加载器负责执行的,具体实现过程为,先创建类加载器对象,然后调用它的loadClass(String)方法,在loadClass方法中先调用findLoadedClass(String)方法以检查该类是否已经被加载过,如果已经加载则直接返回被加载的Class对象;如果没有加载,则调用父类加载器对象的loadClass(String)方法来加载该类,依次递归,直到将加载请求发送给BootStrap类加载器,Bootstrap类加载器拥有加载类的优先权,对于符合其加载路径的class文件都将会由Bootstrap加载进JVM。否则将加载的任务交给子类加载器,依次递归。当所有的父类加载器都不能完成加载指定的类文件时,将由当前类加载器来直接加载。加载的直接结果就是返回指定类对应的字节码对象。
ClassLoader类加载器的实现细节_第1张图片

你可能感兴趣的:(java架构师)