美文网首页
Java类加载源码阅读

Java类加载源码阅读

作者: a0f39b0b2030 | 来源:发表于2018-11-06 15:39 被阅读2次

启动类加载器 BootStrap ClassLoader:最顶层的类加载器,负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。可以通System.getProperty("sun.boot.class.path")查看加载的路径。

扩展类加载器 Extention ClassLoader:主要加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件,或通过java.ext.dirs系统变量指定路径中的类库。也可以通过System.out.println(System.getProperty("java.ext.dirs"))查看加载类文件的路径。

应用程序类加载器 Application ClassLoader:也叫做系统类加载器,可以通过getSystemClassLoader()获取,负责加载用户路径classpath上的类库。如果没有自定义类加载器,一般这个就是默认的类加载器。

类加载层次关系

类加载器之间的这种层次关系叫做双亲委派模型。

双亲委派模型要求除了顶层的启动类加载器(Bootstrap ClassLoader)外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不是以继承关系实现的,而是用组合实现的。

下面看一段源码

public class Launcher {    private static Launcher launcher = new Launcher();    private static String bootClassPath =        System.getProperty("sun.boot.class.path");

    public static Launcher getLauncher() {        return launcher;

    }    private ClassLoader loader;

    public Launcher() {        // Create the extension class loader

        ClassLoader extcl;        try {

            extcl = ExtClassLoader.getExtClassLoader();

        } catch (IOException e) {            throw new InternalError(                "Could not create extension class loader", e);

        }        // Now create the class loader to use to launch the application

        try {

            loader = AppClassLoader.getAppClassLoader(extcl);

        } catch (IOException e) {            throw new InternalError(                "Could not create application class loader", e);

        }        Thread.currentThread().setContextClassLoader(loader);

    }    /*

     * Returns the class loader used to launch the main application.

     */

    public ClassLoader getClassLoader() {        return loader;

    }    /*

     * The class loader used for loading installed extensions.

     */

    static class ExtClassLoader extends URLClassLoader {}    /**

      * The class loader used for loading from java.class.path.

      * runs in a restricted security context.

      */

    static class AppClassLoader extends URLClassLoader {}

复制代码

从源码中我们看到

(1)Launcher初始化的时候创建了ExtClassLoader以及AppClassLoader,并将ExtClassLoader实例传入到AppClassLoader中。

(2)虽然上一段源码中没见到创建BoopStrap ClassLoader,但是程序一开始就执行了System.getProperty("sun.boot.class.path")。

附上Launcher相关文章:blog.csdn.net/jyxmust/art…

类加载器中的继承关系AppClassLoader的父加载器为ExtClassLoader,ExtClassLoader的父加载器为null,BoopStrap ClassLoader为顶级加载器。

类加载机制-双亲委托

当JVM加载Test.class类的时候

首先会到自定义加载器中查找,看是否已经加载过,如果已经加载过,则返回该类。

如果自定义加载器没有加载过,则询问上一层加载器(即AppClassLoader)是否已经加载过Test.class。

如果没有加载过,则询问上一层加载器(ExtClassLoader)是否已经加载过。

如果没有加载过,则继续询问上一层加载(BoopStrap ClassLoader)是否已经加载过。

如果BoopStrap ClassLoader没有加载过,则到自己指定类加载路径sun.boot.class.path下查看是否有Test.class字节码,有则加载并返回加载后的类c = findBootstrapClassOrNull(name)。

如果还是没找到调用c = findClass(name)到加载器ExtClassLoader指定的类加载路径java.ext.dirs下查找class文件,有则加载并返回类。

依此类推,最后到自定义类加载器指定的路径还没有找到Test.class字节码,则抛出异常ClassNotFoundException。

这里注意

每个自定义的类加载器都需要重写findClass方法,该方法的作用是到指定位置查找class文件并加载到JVM中,如果找不到则抛出ClassNotFoundException异常。

双亲委派模型最大的好处就是让Java类同其类加载器一起具备了一种带优先级的层次关系。这句话可能不好理解,我们举个例子。比如我们要加载顶层的Java类——java.lang.Object类,无论我们用哪个类加载器去加载Object类,这个加载请求最终都会委托给Bootstrap ClassLoader,这样就保证了所有加载器加载的Object类都是同一个类。

冷链车APP开发找捌跃科技

双亲委派模型的实现比较简单,在java.lang.ClassLoader的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;

        }

    }

复制代码

/**

     * Finds the class with the specified <a href="#name">binary name</a>.

     * This method should be overridden by class loader implementations that

     * follow the delegation model for loading classes, and will be invoked by

     * the {@link #loadClass <tt>loadClass</tt>} method after checking the

     * parent class loader for the requested class.  The default implementation

     * throws a <tt>ClassNotFoundException</tt>.

     *

     * @param  name

     *         The <a href="#name">binary name</a> of the class

     *

     * @return  The resulting <tt>Class</tt> object

     *

     * @throws  ClassNotFoundException

     *          If the class could not be found

     *

     * @since  1.2

     */

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

    }

转自:http://blog.51cto.com/13902811/2300030

相关文章

  • 浅析java类加载源码及测试

    浅析java类加载源码及测试 时间:20180225 类加载ClassLoader的源码中最重要的是ClassLo...

  • Java类加载源码阅读

    JVM自带加载器 启动类加载器 BootStrap ClassLoader:最顶层的类加载器,负责加载 JAVA_...

  • Java类加载源码阅读

    启动类加载器 BootStrap ClassLoader:最顶层的类加载器,负责加载 JAVA_HOME\lib ...

  • JVM内存模型与数据结构

    JAVA代码执行过程 JAVA源码编译由三个过程组成:源码编译机制、类加载机制、类执行机制。代码编译由JAVA源码...

  • Tomcat源码分析 -- Tomcat类加载器

    本章结构如下: 前言 Java类加载机制 tomcat类加载器 tomcat类加载器源码分析 一、前言 下载tom...

  • 结合JVM源码谈Java类加载器

    一、前言 之前文章 Java 类加载器揭秘 从Java层面讲解了Java类加载器的原理,这里我们结合JVM源码在稍...

  • Java基础:类加载器

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 1. 什么是类加...

  • Java类加载器 java面试那些jvm的鬼

    Java类加载器 类加载器(class loader) 用来加载 Java 类到 Java 虚拟机中。Java 源...

  • JVM性能调优

    JVM类加载机制详解 从JDK源码级别深度剖析加载全过程 启动类、扩展类、应用程序类加载器源码深度剖析 类加载双亲...

  • JVM类加载相关笔记

    Java类加载器 虚拟机自带的类加载器 启动类加载器(Bootstrap)C++加载Java的核心类($JAVA_...

网友评论

      本文标题:Java类加载源码阅读

      本文链接:https://www.haomeiwen.com/subject/vlyuxqtx.html