Java技术之旅深度分析ClassLoader运行机制「 入门篇」

Posted 浩宇の天尚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java技术之旅深度分析ClassLoader运行机制「 入门篇」相关的知识,希望对你有一定的参考价值。

前提概要

Java中的所有类必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘(或者其他介质)读取到JVM内存中,JVM加载类的时候,都是通过ClassLoaderloadClass()方法来加载class的,loadClass使用双亲委派模式

文章目录



源码分析

ClassLoader的介绍

ClassLoader类是一个抽象类,sun公司是这么解释这个类的:

public abstract class 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.
**/

大致意思如下

类加载器是一个负责加载class的对象,ClassLoader类是一个抽象类,需要给出类的二进制名称,类加载器尝试定位或者产生一个class的数据,一个典型的策略是把二进制名字转换成文件名然后到文件系统中找到该文件。

loadClass方法的实现方式:
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;
        


还是来看sun公司对该方法的解释:
/**
     * Loads the class with the specified <a href="#name">binary name</a>.  The
     * default implementation of this method searches for classes in the
     * following order:
     * <p><ol>
     *   <li><p> Invoke @link #findLoadedClass(String) to check if the class
     *   has already been loaded.  </p></li>
     *   <li><p> Invoke the @link #loadClass(String) <tt>loadClass</tt> method
     *   on the parent class loader.  If the parent is <tt>null</tt> the class
     *   loader built-in to the virtual machine is used, instead.  </p></li>
     *
     *   <li><p> Invoke the @link #findClass(String) method to find the
     *   class.  </p></li>
     *
     * </ol>
     *
     * <p> If the class was found using the above steps, and the
     * <tt>resolve</tt> flag is true, this method will then invoke the @link
     * #resolveClass(Class) method on the resulting <tt>Class</tt> object.
     *
     * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override @link
     * #findClass(String), rather than this method.  </p>
     *
     * <p> Unless overridden, this method synchronizes on the result of
     * @link #getClassLoadingLock <tt>getClassLoadingLock</tt> method
     * during the entire class loading process.
     *
     */

大致内容如下

使用指定的二进制名称来加载类,这个方法的默认实现按照以下顺序查找类:
  1. 调用findLoadedClass(String)方法检查这个类是否被加载过
  2. 使用父加载器调用loadClass(String)方法
  3. 如果父加载器为Null,类加载器装载虚拟机启动型加载器调用findClass(String)方法装载类
  4. 如果按照以上的步骤成功的找到对应的类,并且该方法接收的resolve参数的值为true那么就调用resolveClass(Class)方法来处理类

ClassLoader的子类最好覆盖findClass(String) ,而不是所有方法。这个方法默认在整个装载过程中都是同步的(线程安全的),接下来,我们开始分析该方法。

protected Class loadClass(String name, boolean resolve)

该方法的访问控制符是`protected`,也就是说该方法**同包内和派生类中可用** 返回值类型Class ,这里用到**泛型**。这里使用通配符?作为泛型实参表示对象可以 接受任何类型(类类型)。因为该方法不知道要加载的类到底是什么类,所以就用了通用的泛型。String name要查找的类的名字,boolean resolve,一个标志,true表示将调用resolveClass(c)处理该类

throws ClassNotFoundException 该方法会抛出找不到该类的异常,这是一个非运行时异常

synchronized (getClassLoadingLock(name)) 看到这行代码,我们能知道的是,这是一个同步代码块,那么synchronized的括号中放的应该是一个对象。我们来看getClassLoadingLock(name)方法的作用是什么:


以上是关于Java技术之旅深度分析ClassLoader运行机制「 入门篇」的主要内容,如果未能解决你的问题,请参考以下文章

深入分析Java ClassLoader原理

深入分析Java ClassLoader原理

深入分析Java ClassLoader原理

深入分析Java ClassLoader的原理

Java ClassLoader 原理详细分析

ClassLoader理解和源码分析