java.lang.ClassLoader与java.net.URLClassLoader学习-成都快上网建站

java.lang.ClassLoader与java.net.URLClassLoader学习

第一部分:java.lang.ClassLoader

为湛河等地区用户提供了全套网页设计制作服务,及湛河网站建设行业解决方案。主营业务为网站设计、成都网站制作、湛河网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。 基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例

  1. 构造函数

public abstract class ClassLoader
   
private static native void registerNatives();
    static {
        registerNatives();
    }
    
private ClassLoader(Void unused, ClassLoader parent) {
        this.parent = parent;
        if (ParallelLoaders.isRegistered(this.getClass())) {
            parallelLockMap = new ConcurrentHashMap<>();
            package2certs = new ConcurrentHashMap<>();
            domains =
                Collections.synchronizedSet(new HashSet());
            assertionLock = new Object();
        } else {
            // no finer-grained lock; lock on the classloader instance
            parallelLockMap = null;
            package2certs = new Hashtable<>();
            domains = new HashSet<>();
            assertionLock = this;
        }
    }

2.loadClass方法,该方法为类加载器的主要方法,具体代码如下:

    

 protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            //1.异步保护,防止重复加载同一个class
        synchronized (getClassLoadingLock(name)) {
            //2.首先,检查是否类已经被加载过了
            Class c = findLoadedClass(name);
            if (c == null) {
            //2.1如果该类未被加载过
                    //2.1.1 System.nanoTime()这个方法主要是返回一个系统计时器的当前值,以毫微秒为单位。但是不能用作来计算当前时间,只能通过end-start算出间隔时间
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                    //2.1.2如果有父加载器,即父加载器不为初始加载器,则递归父加载器查看是否加载过
                        c = parent.loadClass(name, false);
                    } else {
                    //2.1.3如果没有父加载器,即父加载器为初始加载器,查找类是否加载,具体看方法
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    //2.1.4如果还是没有该类,则运行findClass方法加载,该方法为虚方法
                    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) {
            //解析class,resolve默认为false
                resolveClass(c);
            }
            return c;
        }
    }

3.getClassLoadingLock(name)方法

 protected Object getClassLoadingLock(String className) {
        Object lock = this;
        if (parallelLockMap != null) {
            Object newLock = new Object();
            lock = parallelLockMap.putIfAbsent(className, newLock);
            if (lock == null) {
                lock = newLock;
            }
        }
        return lock;
    }


4.findLoadedClass(name)方法

   protected final Class findLoadedClass(String name) {
        if (!checkName(name))
            return null;
        return findLoadedClass0(name);
    }

    private native final Class findLoadedClass0(String name);

5.findBootstrapClassOrNull(name)方法

 private Class findBootstrapClassOrNull(String name)
    {
        if (!checkName(name)) return null;

        return findBootstrapClass(name);
    }

    // return null if not found
    private native Class findBootstrapClass(String name);

6.findClass(name)方法,该方法在ClassLoader中没有具体实现,因此根据不同的情况会重写该方法进行不同情况的判断。

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

7.resolveClass(Class c)方法

 protected final void resolveClass(Class c) {
        resolveClass0(c);
    }

    private native void resolveClass0(Class c);

8.defineClass方法,主要是将字节码class文件进行实例为Class实例。该方法不可覆盖,我们在继承ClassLoader的时候,会重写findClass方法将相关文件转换成jvm可识别的Class实例。必须要在重写的findClass中调用defineClass才可以完成转换的逻辑。

    

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
    {
        protectionDomain = preDefineClass(name, protectionDomain);
        String source = defineClassSourceLocation(protectionDomain);
        Class c = defineClass1(name, b, off, len, protectionDomain, source);
        postDefineClass(c, protectionDomain);
        return c;
    }

9.ClassLoader类的相关测试。


分享标题:java.lang.ClassLoader与java.net.URLClassLoader学习
转载来源:http://kswjz.com/article/gegdpo.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流