返回顶部
首页 > 资讯 > 后端开发 >Android中的类文件和类加载器详情
  • 928
分享到

Android中的类文件和类加载器详情

Android 2022-06-07 20:06:41 928人浏览 独家记忆
摘要

目录一、Java中的类加载器二、Android中的类加载器2.1 BootClassLoader2.2 PathClassLoader2.3 DexClassLoader2.4

目录

一、Java中的类加载器

二、Android中的类加载器

2.1 BootClassLoader

2.2 PathClassLoader

2.3 DexClassLoader

2.4 InMemoryDexClassLoader

三、Dex文件

3.1 Android内存中的Dex文件

3.2 Dex文件的生成

一、Java中的类加载器

首先花点时间回顾一下Java中的三种类加载器:

BootStrap ClassLoader 启动类加载器,它是实现自C/C++的类加载器,用于加载jdk的核心类库,例如

java.lang
java.util
等系统类。JVM的启动需要通过BootStrap ClassLoader来创建一个初始类来完成

Extensions ClassLoader 扩展类加载器,ExtClassLoader,它用于加载一些系统之外的额外功能。

Application ClassLoader 应用类加载器,也称作系统类加载器,它可以通过getSystemClassLoader拿到,也可以称为系统类加载器。

Custom ClassLoader 自定义类加载器,我们可以通过继承

java.lang.ClassLoader类
来实现自己的类加载器,注意,ExtClassLoader和AppClassLoader也是继承自
java.lang.ClassLoader类
的。

总体的加载关系是:null->ExtClassloader->AppClassLoader,需要注意的是,BootStrap ClassLoader无法在Java中通过.class.getClassLoader()访问它的父加载器。

同时,这只代表加载关系,而不代表继承关系,ClassLoader的继承关系如下:

其中:

ClassLoader本身是一个抽象类,定义了主要的一些功能。

SecureClassLoader扩展实现了ClassLoader方面加入权限方面的功能,加强了ClassLoader的安全性。

URLClassLoader通过URL路径,从jar文件和文件夹下加载类和资源。

ExtClassLoader和AppClassLoader,本身都是Launcher应用的内部类,Launcher是Java虚拟机的入口应用,二者都在Launcher中初始化;

双亲委派机制,大致意思就是当一个类加载器去加载某个类时,会优先委托给父加载器去进行加载,而不是自己加载。这样能够有效地保护加载类的安全性,比如我们希望加载一个

java.lang.String
类,在双亲委派机制下,我们就会优先由父类进行加载,而不是我们自己的类加载器去做加载,父类加载器会从指定的,安全的目录下查找String类。如果是我们自己的类加载器中加载该类那么可能会出现一些安全方面的问题。换句话说,你自己定义的
java.lang.String
类是无法被加载的。当然,这个前提是,你得遵循双亲委派机制,如果你重新写个类加载器,自定义了loadClass并且不遵循双亲委派机制,那么双亲委派机制就被打破了。这也是为什么,JVM认为两个类相等不仅仅要类名相等,而且要类加载器相等才是同一个类。

二、Android中的类加载器

区别于标准JVM以Class文件为输入的字节码文件,Android虚拟机采用更为紧凑的Dex文件作为输入文件,无论是Dalvik VM还是ART VM。这样一来,类加载器自然也会有所改变。

Android中的类加载器类型被分为两类:

系统类加载器:PathClassLoader、DexClassLoader、BootClassLoader

自定义类加载器

2.1 BootClassLoader

Android 系统启动时,会使用BootClassLoader来加载常用的类,与SDK中的BootStrap ClassLoader不同的是,它本身不是由C/C++实现的, 而是采用Java实现的,它是ClassLoader的内部类,继承自ClassLoader,本身是一个单例类。应用中无法直接访问到BootClassLoader。

BootClassLoader是在ZyGoteInit的入口方法中,间接调用了preloadClasses方法中,进行创建的,Android在

/framework/base/preloaded-classes
中封装了一系列的预加载类的目录,一些常用类,例如:ContextImpl、Fragment、Dialog等等都在列。预加载之后,应用程序启动时,就不用额外去做加载了。

2.2 PathClassLoader

PathClassLoader它通常被系统用来加载Apk中自带的Dex文件,它的构造函数中少了一个参数:optimizedDirectory,这是因为PathClassLoader定义了默认的optimizedDirectory参数:

/data/dalvik-cache/
,因此,我们无法自定义Dex文件的解压路径,所以我们加载类时,一般都使用DexClassLoader

PathClassLoader是Zygote进程在fork SystemServer进程时创建的,当Zygote进程在新创建SystemServer时,通过调用forkSystemServer方法时,会调用到handleSystemServerProcess(),然后调用createPathClassLoader()去创建PathClassLoader。

2.3 DexClassLoader

可以在磁盘中加载.dex或者是.apk文件,但是本质上都是加载属于Android 的字节码文件:Dex文件。

它的构造方法有四个参数:

dexPath:相关的文件路径;支持多个路径,使用「:」分割

optimizedDirectory:Dex文件解压后的文件存储路径,一般情况下使用当前文件的私有路径。

"this parameter is deprecated and has no effect since api level 26."

注意:optimizedDirectory参数在API26之后被废弃了

librarySearchPath:包含C/c++库的路径集合,可以为null

parent:父加载器

我们通常在App启动时,我们通常使用DexClassLoader动态加载Dex的方式来实现应用程序Java代码层面的热修复。

2.4 InMemoryDexClassLoader

Android8.0 中新增的用于加载内存中的类加载器。和PathClassLoader、DexClassLoader一样,都是BaseDexClassLoader的实现类。

三、Dex文件 3.1 Android内存中的Dex文件

BaseDexClassLoader有三个子类:DexClassLoader、PathClassLoader、InMemoryDexClassLoader,它们三个主要任务就是:加载外部的Dex文件,获取其中定义的类信息。同样,Android的类加载机制也遵循双亲委派机制

BaseDexClassLoader有一个特殊的结构:DexPathList类型的pathList ,它内部维护了一个Element类型的数组,用来存储被加载的Dex文件信息:

private Element[] dexElements;

每当我们要使用一个类时,类加载器就会先检索:DexPathList中的所有Dex文件,逐个遍历,看看其中是否含有所需要的类:

Element内部有一个对象:DexFile,在调用Element#findClass时,会按照如下规则去查找:

而最终,loadClassBinaryName会调用Native代码在本地内存上创建一个指向Dex文件的对象,这样 ,我们知道Dex文件在内存中的引用是类加载下的DexPathList中的一个个Element。

这个Element数组可以作为一个热修复的接入点,我们知道,类加载只会被加载一次,如果此时我们有多个Dex文件,那么Dex文件的引用在Element中会按照加载的顺序排列,这样一来,排在前面的Dex类中的Class就会被优先加载,由此我们就可以将热修复后重新生成的

Patch.dex
Patch.apk
加载到用户手机存储空间当中,然后自行使用DexPathClassLoader进行加载,并通过反射,Hook掉PathClassLoader,将
Patch.dex
对应的Element反射插入到其DexPathList当中去。这样一来,加载时就会优先从
Patch.dex
中加载了,原理大致如下图。修复后加载原先出错的类ClassE将会从Patch.dex中优先加载,而出错的Class E由于类加载的特性,将不会被加载出来。

3.2 Dex文件的生成

我们所编写的Java代码,使用Java自带的编译器编译完成之后默认的输出一定是.class文件,而在ART或者Dalvik虚拟机中需要输入Dex文件,那么在其中必然存在Class -> Dex文件的过程。

该过程是由d8工具完成的,在我们的SDK目录下:

/Library/Android/sdk/build-tools/28.0.3
,有非常多和我们Android 构建相关的一些工具,例如aapt2工具会负责将res.xml中的文件在R.java中生成对应的ID引用、负责将二进制资源、资源表resources.arsc、classes.dex以及assets集成打包进一个未签名的.apk文件内。

d8工具会将需要打包的.class文件、额外依赖的Jar文件一同参与编译。比如我们需要对appt2下的一个MainActivity.class文件进行编译,那么我们可以在一个新项目中,点击Android Studio的编译或者上面的绿色小锤子,然后在:

MyApplication2/app/build/intermediates/javac/debug/classes/com/red/myapplication
 下我看到MainActicity.class文件,然后在该目录下执行如下的指令,注意,将MainActivity的AppcompatActivity换成Activity,因为前者是属于AndroidX系列的的AAR包中的依赖,需要额外添加。

d8 aapt/MainActivity.class
 --lib /Library/Android/sdk/platfORMs/android-29/android.jar
 --output ./

其中,

--lib
指定了一些额外的依赖,因为MainActivity中会依赖
android.jar
中的一些文件(比如Activity类),完成后,我们就得到了一个classes.dex文件,结构如下:

如上的步骤都在Android提供的Gradle套件中,帮我们完成了,Gradle插件依赖的本质,就是插件文件的下载(Gradle同步)和引用。

到此这篇关于Android 中的类文件和类加载器详情的文章就介绍到这了,更多相关Android 类文件 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


--结束END--

本文标题: Android中的类文件和类加载器详情

本文链接: https://lsjlt.com/news/30544.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android中的类文件和类加载器详情
    目录一、Java中的类加载器二、Android中的类加载器2.1 BootClassLoader2.2 PathClassLoader2.3 DexClassLoader2.4...
    99+
    2022-06-07
    Android
  • Android中的类文件和类加载器实例分析
    本篇内容介绍了“Android中的类文件和类加载器实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Java中的类加载器首先花点时间...
    99+
    2023-06-30
  • Android虚拟机与类加载机制详情
    目录JVM与Dalvik基于栈的虚拟机字节码指令执行过程基于寄存器的虚拟机寄存器基于寄存器的虚拟机ART与Dalvikdex2aotdexopt与dexaotAndroid N的运作...
    99+
    2024-04-02
  • 一文详解Java中的类加载机制
    目录一、前言二、类加载的时机2.1 类加载过程2.2 什么时候类初始化2.3 被动引用不会初始化三、类加载的过程3.1 加载3.2 验证3.3 准备3.4 解析3.5 初始化四、父类...
    99+
    2024-04-02
  • Java类加载过程与类加载器详细介绍
    目录1. 类加载过程加载链接初始化2. 类加载器启动类加载器扩展类加载器应用类加载器自定义类加载器双亲委派模型1. 类加载过程 加载 通过类的全限定名(包名 + 类名),获取到类的...
    99+
    2022-11-13
    Java 类加载过程 Java加载器
  • Java 中的类和对象详情
    目录1、类的定义2、类中变量的类型3、构造方法4、重载方法5、继承5.1 重写方法6、创建对象7、访问实例变量和方法8、比较对象8.1 使用 == 比较对象8.2 使用 equals...
    99+
    2024-04-02
  • java类加载器ClassLoader详解
    获得ClassLoader的途径 获得当前类的ClassLoaderclazz.getClassLoader() 获得当前线程上下文的ClassLoaderThread.currentThread().getContextClassLoad...
    99+
    2019-01-28
    java基础 类加载器 ClassLoader
  • Java 中的 File类详情
    目录一、File类简单介绍二、 路径的分类三、 构造方法四、 成员方法一、File类简单介绍 为什么要学习File类呢,他的作用又是什么呢? IO流操作中大部分都是对文件进行...
    99+
    2024-04-02
  • Android中怎么利用HttpUrlConnection类下载文件
    Android中怎么利用HttpUrlConnection类下载文件,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。具体代码如所示:  pri...
    99+
    2023-05-30
    android httpurlconnection
  • JVM入门之类加载与字节码技术(类加载与类的加载器)
    目录1. 类加载阶段1.1 加载阶段1.2 链接阶段准备1.3 初始化阶段1.4 练习2. 类加载器2.1 启动类加载器2.2 扩展类加载器2.3 双亲委派模式2.4 线程上下文类加...
    99+
    2024-04-02
  • 浅析PHP中的类自动加载相关文件
    本篇文章给大家带来了关于PHP的相关知识,其中主要介绍了类自动加载的相关内容,下面带大家一起来分析下PHP中类自动加载相关文件,希望对大家有帮助。PHP 中类自动加载相关文件分析类自动加载Composer 是一种 PHP 包管理工具,可用于...
    99+
    2023-05-14
    php
  • 概述java虚拟机中类的加载器及类加载过程
    目录1. 类加载子系统 1.1 概述1.2 类的加载器2.类的加载过程2.1 类的加载过程简图2.2 加载阶段:Loading2.3 链接阶段:Linking2.4 初始化...
    99+
    2024-04-02
  • Android图片加载的缓存类
    本文为大家分享了Android图片加载的缓存类,供大家参考,具体内容如下 import java.io.File; import java.io.FileInputStre...
    99+
    2022-06-06
    缓存 Android
  • Java中类的加载器及其加载过程
    目录Java中类的加载器及其加载过程概述过程一:Loading过程二:Linking过程三:InitializationJava中类的加载器及其加载过程 概述 字节码文件在类加载器子...
    99+
    2023-05-16
    Java类的加载器 Java类加载过程 加载器加载过程
  • Java类加载器ClassLoader的使用详解
    目录BootstrapClassLoaderExtClassLoaderAppClassLoader类加载器的具体实现在哪里类加载器的初始化时机如何进行的类加载Loader.getR...
    99+
    2022-12-19
    Java类加载器ClassLoader Java ClassLoader Java类加载器
  • React 函数式组件和类式组件详情
    目录前言1. 函数式组件2. 类式组件前言 React 是 组件化的 的 JS 库,组件化 也是 React 的核心思想。使用 React 可以构建管理...
    99+
    2022-11-13
    React 函数式组件 React 类式组件
  • python中的元类metaclass详情
    目录动机从一个问题引出 MetaClassMetaclass 编程动机 python语言因为工作偏向于 AI ,所以对于这门语言还停留在表面,对于 python 深层并没有接触到。 ...
    99+
    2024-04-02
  • PHP中的类自动加载相关文件有哪些
    本文小编为大家详细介绍“PHP中的类自动加载相关文件有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“PHP中的类自动加载相关文件有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。PHP 中类自动加载相关文...
    99+
    2023-07-04
  • Java类加载的过程详解
    目录Java:类加载过程1.加载——3件事2.连接2.1.验证2.2.准备2.3.解析3.初始化总结Java:类加载过程 1.加载——3件事 1.通过全类名获取定义此类的...
    99+
    2024-04-02
  • Python中的变量和数据类型详情
    python是一门弱数据类型的语言,变量不需要声明即可使用,向变量赋值即定义变量,赋予的值的类型就是变量的类型,但变量也是有数据类型的,字符串'1'如果想参与数据计算...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作