您的位置:

深入理解Android ClassLoader机制的实现原理

深入理解Android ClassLoader机制的实现原理

更新:

一、ClassLoader概述

ClassLoader(类加载器)是Java虚拟机的一项核心技术,实现了虚拟机动态加载类及其依赖的特性。ClassLoader主要负责查找并加载类文件,将其转换成Java类,在需要的时候初始化类,并为Java程序提供必要的运行时环境。在Android系统中,ClassLoader也占据了同样的核心位置。

Android应用程序运行在DVM(Dalvik虚拟机)或ART(Android Runtime)上,这两个运行时环境使用的ClassLoader也不同。DVM使用的ClassLoader是PathClassLoader,它是一种基于Dex文件的类加载器。ART使用的ClassLoader是ArtClassLoader,它是一种基于Oat文件的类加载器。以下我们将以PathClassLoader为例,详细介绍Android ClassLoader机制的实现原理。

二、ClassLoader分类

ClassLoader的实现机制不一,根据具体的实现方式,可以将ClassLoader分为以下几种类型:

1. BootStrap ClassLoader

负责加载JVM运行需要的基础类库(如rt.jar、i18n.jar、sunrsasign.jar等)。BootStrap ClassLoader是JVM内置的ClassLoader,并不继承自java.lang.ClassLoader,它是用C++编写的,提供了JVM的基础服务。

2. Extension ClassLoader

负责加载JRE扩展的类库(如jce.jar、localedata.jar等)。Extension ClassLoader是由Sun的扩展类加载器实现的,它继承自ClassLoader,它的父类加载器是BootStrap ClassLoader。

3. Application ClassLoader

也称作System ClassLoader,是ClassLoader的默认实现。它负责加载CLASSPATH路径下的类文件和应用程序本身的类文件。Application ClassLoader是Java应用程序开发中,开发人员最关心的ClassLoader实现之一。

另外的还有自定义ClassLoader,它可以继承ClassLoader并重新实现加载机制。开发人员可以使用自定义ClassLoader加载特定的类文件或按照特定规则实现类的加载,从而实现一些特定的功能。

三、ClassLoader实现原理

ClassLoader机制的实现依赖于ClassLoader的双亲委派机制。在ClassLoader加载类的时候,首先询问它的父类加载器是否能够加载该类,如果不能,则自身尝试加载。如果自身不能加载,则逐级向上委派,直至BootStrap ClassLoader都不能加载,最终由自身去完成类的加载。这种方式保证了一个类在虚拟机中只有一个版本(不同的ClassLoader实例会加载不同的版本,无法互相访问),避免了类的重复加载,也保证了类的安全性。

ClassLoader机制的实现过程大致可以分为以下几个步骤:

1. 对于需要加载的类,首先从缓存中查找是否已经加载过。

ClassLoader会将已经加载成功的类文件缓存在内存中,以便下次使用时可以直接从缓存中获取。如果已经存在,则返回成功加载的类对象。

2. 如果没有找到可用的缓存,则请求父ClassLoader进行加载。

ClassLoader在委托父ClassLoader之前,先使用findLoadedClass()方法再进行一次查找,以避免出现重复加载的现象。如果父ClassLoader存在,则请求父ClassLoader进行加载。如果父ClassLoader也无法加载,则继续向上委派,直至委派到BootStrap ClassLoader。

3. 如果所有的父ClassLoader都无法加载,则从本地文件系统或者网络等位置获取要加载的.class文件。

ClassLoader在查找.class文件的时候,会根据一定规则查找指定路径下的.class文件。一般包括CLASSPATH路径、系统默认路径以及其他用户自定义的路径。如果能够查找到要加载的.class文件,则将它转换成Java类并返回。否则,抛出ClassNotFoundException。

4. 将加载成功的类文件存储到缓存中。

为了以后可以重用已经成功加载的类文件,ClassLoader会将成功加载的类文件存储到缓存中,下次再使用时可以直接从缓存中获取。

四、Class对象与ClassLoader

每个Java类在虚拟机中都有一个对应的Class对象,ClassLoader负责将类文件加载到虚拟机中,并转换成Class对象。通过Class对象,可以获取类的信息,包括类名、父类、接口、字段、方法等信息。ClassLoader不仅加载类文件,它还负责创建和管理Class对象,即ClassLoader与Class对象是一一对应的关系。ClassLoader利用类的全限定名来查找并加载类,因此不同的ClassLoader实例可以加载同名的类,但这些类之间是互不共享的,可以看成具有相同类名但具有不同命名空间的不同类。

以下是一个简单的例子,介绍ClassLoader和Class对象的关系:

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取系统ClassLoader
        ClassLoader cl = ClassLoader.getSystemClassLoader();

        // 加载Hello类
        Class c = cl.loadClass("com.example.Hello");

        // 输出Hello的类名
        System.out.println("类名:" + c.getName());

        // 输出Hello的Class对象的ClassLoader
        System.out.println("ClassLoader:" + c.getClassLoader());
    }
}

以上代码中,使用ClassLoader.getSystemClassLoader()方法获取系统ClassLoader,然后使用ClassLoader加载指定的类。最后输出类的名称和ClassLoader。在Java中,类的名称是唯一的,而ClassLoader是有继承链的。因此在ClassLoader的继承链上,可以有多个ClassLoader实例同时加载同名的类。另外,需要注意,系统ClassLoader是默认的ClassLoader,如果没有指定ClassLoader,一般都会使用系统ClassLoader。

五、注意事项

ClassLoader机制对程序的运行维护起到了重要的作用,但是在使用时还需要注意以下事项:

1. 类的可访问性

当ClassLoader加载一个类时,要保证该类的访问性。如果类文件的可访问性限制了访问该类的ClassLoader的话,则会抛出SecurityException异常。

2. 类的初始化时机

一个类只有被使用时才会被初始化。类的初始化是指虚拟机为该类生成Class对象,并且在内存中分配资源。类的初始化时机包括:创建该类的实例对象、访问类的静态成员(被final修饰的静态成员除外)、使用是客户端JVM所在的Java程序启动时被标明为启动类的类、使用了反射API的类等。如果一个类没有被使用,则不会被加载和初始化,即便ClassLoader已经加载了该类的字节码文件。

3. 线程上下文ClassLoader

线程上下文ClassLoader用于在多个线程中对ClassLoader进行传递和继承。线程的上下文ClassLoader可以通过Thread类的setContextClassLoader()方法设置。当一个线程需要加载一个类时,它首先尝试使用自己的ClassLoader,如果未找到,则使用其线程上下文ClassLoader。如果该线程上下文ClassLoader也未找到,则委托父线程的上下文ClassLoader进行查找,直至BootStrap ClassLoader。线程上下文ClassLoader基本上是由应用程序自行负责管理的,JVM在不同的线程中使用不同的ClassLoader对同一类进行加载时,可能会导致出现问题。因此,在引入第三方类库、动态加载类和OSGi等场景下,都需要注意ClassLoader的使用。

六、总结

ClassLoader是Java虚拟机的基础服务,它提供了Java程序动态加载类的能力。Android应用程序同样运用了ClassLoader机制,用于实现在运行时动态加载和卸载类。ClassLoader加载类的过程遵循双亲委派机制,保证了类在虚拟机中的唯一性和安全性。ClassLoader机制是Java和Android程序设计不可或缺的一部分,熟练掌握ClassLoader的使用,对程序的设计和性能优化有很大的帮助。

深入理解Android ClassLoader机制的实现原理

一、ClassLoader概述 ClassLoader(类加载器)是Java虚拟机的一项核心技术,实现了虚拟机动态加载类及其依赖的特性。ClassLoader主要负责查找并加载类文件,将其转换成Jav

2023-12-08
深入理解Android的Binder机制

2023-05-14
深入理解Android AIDL通信机制

2023-05-14
深入理解Android View绘制机制

2023-05-14
Android:深入理解事件分发机制实现原理

2023-05-14
如何使用Android ClassLoader优化应用程序性

2023-05-20
深入理解Android内存泄漏检测工具LeakCanary原

一、LeakCanary简介 在Android开发中,内存泄漏一直是一个难题。为了解决这一问题,Square Open Source团队开发了一款内存泄漏检测库:LeakCanary。LeakCana

2023-12-08
深入了解Android 33

2023-05-22
Android SPI机制:插件化开发必备

2023-05-14
VirtualAPK:轻松实现Android应用模块化

2023-05-20
解密Android Binder机制:实现进程间通信

一、前言 在Android系统中,各个应用程序之间需要进行进程间通信,以实现数据共享和交互功能。Binder机制是Android系统中最核心、最基础的进程间通信方式。本文将对Android Binde

2023-12-08
提高Android应用性能的关键:深入理解Android R

2023-05-14
Android Binder:实现进程间通信的核心机制

Android系统的进程间通信(IPC)机制是整个系统中最重要的部分之一,这个机制让不同的进程之间能够交换数据和信息。在Android系统中,主要采用的IPC机制是Binder机制。Binder机制的

2023-12-08
深入理解Android中的android:minifyEna

2023-05-20
Xposed框架简介及实现定制化功能教程

2023-05-14
Android JSBridge实现原理和使用方法

一、什么是Android JSBridge Android JSBridge是一种可以实现Android应用与H5页面之间相互通信的桥梁技术。通过JSBridge,H5页面可以调用Android应用中

2023-12-08
了解ClassLoader的重要性及使用方法

2023-05-16
Android应用中广播的实现原理及优化

2023-05-14
Android子系统-内存管理方案实现

2023-05-14
学习aop之java的代理机制(aop jdk动态代理原理)

2022-11-12