20191501_ClassLoader源码解析

/*
 * A class loader is an object that is responsible for loading classes. The
 * class <tt>ClassLoader</tt> is an abstract class.  Given the <a
 * href="#name">binary name</a> of a class, a class loader should attempt to
 * locate or generate data that constitutes a definition for the class.  A
 * typical strategy is to transform the name into a file name and then read a
 * "class file" of that name from a file system.
*/

ClassLoader用于尝试定位或者生成Class对象。通常采用将名字转换为文件名,然后通过文件系统读取该文件。

ClassLoader需要注意以下三个方法:

  1. loadClass : 运行时可以通过调用此方法加载一个类。此方法会尝试委托给父类去加载。若想打破双亲委托机制,需要重写这个方法。
  2. findClass : 通过类名去加载对应的Class对象。当我们实现自定义的classLoader通常是重写这个方法,根据传入的类名找到对应字节码的文件,并通过调用defineClass解析出Class独享。
  3. defineClass:将byte字节流解析为JVM能够识别的Class对象。

loadClass

public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        Class<?> c = findLoadedClass(name);
        // 没被加载,就委托父类加载器
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            //如果父类加载器不能加载,需要自己去加载
            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

findClass

protected Class<?> findClass(String name) throws ClassNotFoundException {
    throw new ClassNotFoundException(name);
}

来看AppClassLoader的实现,它是由父类URLClassLoader实现的:

protected Class<?> findClass(final String name)
    throws ClassNotFoundException
{
    final Class<?> result;
    try {
        result = AccessController.doPrivileged(
            new PrivilegedExceptionAction<Class<?>>() {
                public Class<?> run() throws ClassNotFoundException {
                    String path = name.replace('.', '/').concat(".class");
                    Resource res = ucp.getResource(path, false);
                    if (res != null) {
                        try {
                            // 通过调用defineClass去实现
                            return defineClass(name, res);
                        } catch (IOException e) {
                            throw new ClassNotFoundException(name, e);
                        }
                    } else {
                        return null;
                    }
                }
            }, acc);
    } catch (java.security.PrivilegedActionException pae) {
        throw (ClassNotFoundException) pae.getException();
    }
    if (result == null) {
        throw new ClassNotFoundException(name);
    }
    return result;
}

defineClass

/**
* @param  name
*         The expected <a href="#name">binary name</a> of the class, or
*         <tt>null</tt> if not known
*
* @param  b
*         The bytes that make up the class data.  The bytes in positions
*         <tt>off</tt> through <tt>off+len-1</tt> should have the format
*         of a valid class file as defined by
*         <cite>The Java&trade; Virtual Machine Specification</cite>.
*
* @param  off
*         The start offset in <tt>b</tt> of the class data
*
* @param  len
*         The length of the class data
*/
protected final Class<?> defineClass(String name, byte[] b, int off, int len)
    throws ClassFormatError
{
    return defineClass(name, b, off, len, null);
}
protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                     ProtectionDomain protectionDomain)
    throws ClassFormatError
{
    //该方法会用来校验待加载类的信息,比如:java开头的类会直接抛出异常。
    protectionDomain = preDefineClass(name, protectionDomain);
    //获取与此 域的CodeSource 关联的位置
    String source = defineClassSourceLocation(protectionDomain);
    //native方法, 获取Class对象
    Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
   //从该类的 ProtectionDomain 中的 CodeSource 可以获得类的证书集合。 添加到该包中的任何类都必须包含相同的证书集合
   postDefineClass(c, protectionDomain);
   return c;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值