Android解析ClassLoader(一)Java中的ClassLoader

title: “Android解析ClassLoader(一)Java中的ClassLoader”
date: 2017-09-25 00:16
tag:

  • Android应用层
  • ClassLoader
    categories:
  • Android应用层

本文首发于微信公众号「刘望舒」

关联系列
Java虚拟机系列
Android解析ClassLoader系列

前言

热修复和插件化是目前比较热门的技术,要想更好的掌握它们需要了解ClassLoader,因此也就有了本系列的产生,这一篇我们先来学习Java中的ClassLoader。

1.ClassLoader的类型

Java虚拟机(一)结构原理与运行时数据区域这篇文章中,我提到过类加载子系统,它的主要作用就是通过多种类加载器(ClassLoader)来查找和加载Class文件到 Java 虚拟机中。
Java中的类加载器主要有两种类型,系统类加载和自定义类加载器。其中系统类加载器包括3种,分别是Bootstrap ClassLoader、 Extensions ClassLoader和 App ClassLoader。

1.1 Bootstrap ClassLoader

用C/C++代码实现的加载器,用于加载Java虚拟机运行时所需要的系统类,如java.lang.*、java.uti.*等这些系统类,它们默认在$JAVA_HOME/jre/lib目录中,也可以通过启动Java虚拟机时指定-Xbootclasspath选项,来改变Bootstrap ClassLoader的加载目录。
Java虚拟机的启动就是通过 Bootstrap ClassLoader创建一个初始类来完成的。由于Bootstrap ClassLoader是使用C/C++语言实现的, 所以该加载器不能被Java代码访问到。需要注意的是Bootstrap ClassLoader并不继承java.lang.ClassLoader。
我们可以通过如下代码来得出Bootstrap ClassLoader所加载的目录:

public class ClassLoaderTest {
   
    public static void main(String[]args) {
   
        System.out.println(System.getProperty("sun.boot.class.path"));
    }
}

打印结果为:

C:\Program Files\Java\jdk1.8.0_102\jre\lib\resources.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\lib\rt.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\lib\sunrsasign.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\lib\jsse.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\lib\jce.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\lib\jfr.jar;
C:\Program Files\Java\jdk1.8.0_102\jre\classes

可以发现几乎都是$JAVA_HOME/jre/lib目录中的jar包,包括rt.jar、resources.jar和charsets.jar等等。

1.2 Extensions ClassLoader

用于加载 Java 的拓展类 ,拓展类的jar包一般会放在$JAVA_HOME/jre/lib/ext目录下,用来提供除了系统类之外的额外功能。也可以通过-Djava.ext.dirs选项添加和修改Extensions ClassLoader加载的路径。
通过以下代码可以得到Extensions ClassLoader加载目录:

System.out.println(System.getProperty("java.ext.dirs"));

打印结果为:

C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext;
C:\Windows\Sun\Java\lib\ext
1.3 App ClassLoader

负责加载当前应用程序Classpath目录下的所有jar和Class文件。也可以加载通过-Djava.class.path选项所指定的目录下的jar和Class文件。

1.4 Custom ClassLoader

除了系统提供的类加载器,还可以自定义类加载器,自定义类加载器通过继承java.lang.ClassLoader类的方式来实现自己的类加载器,除了 Bootstrap ClassLoader,Extensions ClassLoader和App ClassLoader也继承了java.lang.ClassLoader类。关于自定义类加载器后面会进行介绍。

2.ClassLoader的继承关系

运行一个Java程序需要用到几种类型的类加载器呢?如下所示。

public class ClassLoaderTest {
   
    public static void main(String[] args) {
   
        ClassLoader loader = ClassLoaderTest.class.getClassLoader();
        while (loader != null) {
   
            System.out.println(loader);//1
            loader = loader.getParent();
        }
    }
}

首先我们得到当前类ClassLoaderTest的类加载器,并在注释1处打印出来,接着打印出当前类的类加载器的父加载器,直到没有父加载器终止循环。打印结果如下所示。

sun.misc.Launcher$AppClassLoader@75b84c92
sun.misc.Launcher$ExtClassLoader@1b6d3586

第1行说明加载ClassLoaderTest的类加载器是AppClassLoader,第2行说明AppClassLoader的父加载器为ExtClassLoader。至于为何没有打印出ExtClassLoader的父加载器Bootstrap ClassLoader,这是因为Bootstrap ClassLoader是由C/C++编写的,并不是一个Java类,因此我们无法在Java代码中获取它的引用。

我们知道系统所提供的类加载器有3种类型,但是系统提供的ClassLoader相关类却不只3个。另外,AppClassLoader的父类加载器为ExtClassLoader,并不代表AppClassLoader继承自ExtClassLoader,ClassLoader的继承关系如下所示。

VmZfXD.png

可以看到上图中共有5个ClassLoader相关类,下面简单对它们进行介绍:

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值