一、Java中的ClassLoader是什么?

当写好一个Java应用程序,程序都是由若干个.class类文件组织而成的,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常。而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需要,通过Java的类加载机制(ClassLoader)来动态加载某个class文件到JVM中,从而只有class文件被载入到了JVM之后,才能被其它class所引用。所以ClassLoader就是用来动态加载class文件到JVM当中用的。

简单的说Java中的ClassLoader就是加载 class 文件,提供给程序运行时使用。

二、java中ClassLoader加载原理

1、原理介绍

ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时。加载过程是:

1.源 ClassLoader 先判断该 Class 是否已加载,如果已加载,则直接返回 Class,如果没有则委托给父类加载器。

2.父类加载器判断是否加载过该 Class,如果已加载,则直接返回 Class,如果没有则委托给祖父类加载器。

3.依此类推,直到始祖类加载器(引用类加载器)。

4.始祖类加载器判断是否加载过该 Class,如果已加载,则直接返回 Class,如果没有则尝试从其对应的类路径下寻找 class 字节码文件并载入。如果载入成功,则直接返回 Class,如果载入失败,则委托给始祖类加载器的子类加载器。

5.始祖类加载器的子类加载器尝试从其对应的类路径下寻找 class 字节码文件并载入。如果载入成功,则直接返回 Class,如果载入失败,则委托给始祖类加载器的孙类加载器。

6.依此类推,直到源 ClassLoader。

7.源 ClassLoader 尝试从其对应的类路径下寻找 class 字节码文件并载入。如果载入成功,则直接返回 Class,如果载入失败,源 ClassLoader 不会再委托其子类加载器,而是抛出异常。

jdk源码中的ClassLoader

2、JVM中是如何判定两个class是相同的呢?

JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。只有两者同时满足的情况下,JVM才认为这两个class是相同的。就算两个class是同一份class字节码,如果被两个不同的ClassLoader实例所加载,JVM也会认为它们是两个不同class。

同一个Class = 相同的 ClassName + PackageName + ClassLoader

如果想了解更加具体请看如下链接:

三、Android 中的 ClassLoader

Android 的 Dalvik(5.0之前版本)/ART(5.0增加的) 虚拟机如同标准 Java 的 JVM 虚拟机一样,也是同样需要加载 class 文件到内存中来使用,但是在 ClassLoader 的加载细节上会有略微的差别。

Android打包之后的apk 应用,将apk的后缀名改成zip或rar,解压之后会看见有一个或多个 class.dex 文件,用多个dex文件是android使用了MultiDexApplication解决65535的问题。

多个dex文件

android在安装(installer)apk时,就对dex会进行验证和优化,同过一个专门的工具来处理,叫 DexOpt来进行处理,处理之后会产生ODEX文件,运行Apk的时候,直接加载ODEX,避免重复验证和优化,加快了Apk的响应时间。

总之,Android 中的 Dalvik/ART 无法像 JVM 那样直接加载 class 文件和 jar 文件中的 class,需要通过工具来优化转换成 Dalvik byte code 才行,只能通过 dex 或者包含 dex 的jar、apk 文件来加载(注意 odex 文件后缀可能是 .dex 或 .odex,也属于 dex 文件),因此 Android 中的 ClassLoader 工作就交给了 BaseDexClassLoader 来处理。

BaseDexClassLoader 及其子类

从ClassLoader的android源码看ClassLoader是一个abstract类,其具体实现的子类有BaseDexClassLoader和SecureClassLoader。

ClassLoader部门源码

SecureClassLoader 的子类是URLClassLoader,其只能用来加载 jar 文件,这在 Android 的 Dalvik/ART 上没法使用的。

BaseDexClassLoader 的子类是PathClassLoader和DexClassLoader。

PathClassLoader

PathClassLoader 在应用启动时创建,从 data/app/… 安装目录下加载 apk 文件

PathClassLoader源码

dexPath:文件或者目录的列表,dex,apk,多个以文件分隔符分隔,默认是“.”

librarySearchPath:包含lib库的目录列表,多个以文件分隔符分隔,默认是空格

parent:父类加载器

PathClassLoader 里面除了这 2 个构造方法以外就没有其他的代码了,具体的实现都是在 BaseDexClassLoader 里面,其 dexPath 比较受限制,一般是已经安装应用的 apk 文件路径。

在 Android 中,App 安装到手机后,apk 里面的 class.dex 中的 class 均是通过 PathClassLoader 来加载的。

DexClassLoader

A class loader that loads classes from.jar and.apk files containing aclasses.dexentry. This can be used to execute code not installed as part of an application.

根据官方给出的文档 DexClassLoader 可以从 SD 卡上加载包含 class.dex 的 .jar 和 .apk 文件,这也是插件化和热修复的基础,在不需要安装应用的情况下,完成需要使用的 dex 的加载。

DexClassLoader源码

DexClassLoader类就只有一个方法,改方法有四个个参数

dexPath:dex文件路径列表,多个路径使用”:”分隔

dexOutputDir:经过优化的dex文件(odex)文件输出目录

libPath:动态库路径(将被添加到app动态库搜索路径列表中)

parent:这是一个ClassLoader,这个参数的主要作用是保留java中ClassLoader的委托机制(优先父类加载器加载classes,由上而下的加载机制,防止重复加载类字节码)

android的加载是根据BaseDexClassLoader子类进行加载不通的dex而子类的实现都在BaseDexClassLoader中,BaseDexClassLoader是关键,下次分析BaseDexClassLoader源码

android classloader的功能和工作模式,Android中ClassLoader和java中ClassLoader有什么关系和不同...相关推荐

  1. Android面试-LaunchMode及Task工作模式(扔物线笔记)

    切到后台时看到的是任务列表,会列出已存在的Task任务,Activity存活在任务栈中. 一.Activity的LaunchMode有四种: standard (默认),每次都新建一个Activity ...

  2. android视频分享功能吗,Unity 调用 Android 分享功能(基于ShareRec SDK视频分享)

    需求 Mob 平台是一个强大的提供分享功能的平台,为移动开发者提供 ShareSDK 社交分享.ShareREC 手游录像分享.短信验证码 SDK 及 BigApp 等免费服务. Unity 使用 S ...

  3. SPI Flash芯片W25Q32英文版数据手册解读(一)---------引脚功能,工作模式

    W25Q32芯片是一个可以通过SPI(串行外围设备接口)操作的flash存储器,这篇文章备忘和总结一下英文版数据手册的一些解读.有关时序及具体用STC单片机编写程序的内容等下一篇文章. 一.芯片引脚功 ...

  4. JAVA面试要点006---.net中的委托与java中的代理模式和委托

    1.1.1 定义 委托是一种引用方法的类型.一旦为委托分配了方法,委托将与该方法具有完全相同的行为.委托方法的使用可以像其他任何方法一样,具有参数和返回值,如下面的示例所示: //Code in C# ...

  5. 设计模式-抽象工厂模式的应用场景及Java中对抽象工厂的应用

    1. 什么是抽象工厂模式 抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定他们的类 抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用 ...

  6. java 中括号中的语句,Java中是使用大括号括起来的语句块,用于完成一个相对独立的逻辑功能,这种语句被称作()。...

    Java中是使用大括号括起来的语句块,用于完成一个相对独立的逻辑功能,这种语句被称作(). 更多相关问题 下列哪项措施不能提高砌体受压构件的承载力()? 商业银行办理个人储蓄存款业务,应当遵循地原则( ...

  7. android手机常用功能,Windows Phone 7/Android手机常用功能对比

    据资讯网站Neowin报道,近日,微软发布了旗下手机操作系统平台WindowsPhone 7,智能手机领域的局势变得更加扑朔迷离.Neowin网站开辟专栏,就WP7和Android两大平台手机的诸多性 ...

  8. android 悬浮按钮 功能实现,怎么在Android中利用FloatingActionButton实现一个悬浮按钮效果...

    怎么在Android中利用FloatingActionButton实现一个悬浮按钮效果 发布时间:2020-12-02 17:41:30 来源:亿速云 阅读:238 作者:Leah 今天就跟大家聊聊有 ...

  9. android手机怎样开启usb调试模式,Android手机USB调试在哪?安卓手机如何打开USB调试模式?...

    Android手机USB调试在哪?安卓手机如何打开USB调试模式?如果我们要将安卓手机连接到电脑上,从而传输文件.下载应用或ROOT等,都需要打开手机的USB调试模式.安卓系统的版本有很多,它们的打开 ...

最新文章

  1. 机器学习中需要了解的 5 种采样方法
  2. 65个免费和高质量的纹理包
  3. Rancher添加主机docker命令
  4. VS Code Pettier设置换行最大宽度
  5. POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解...
  6. 控制面板项 .cpl 文件说明
  7. c++判断二叉树是否为二叉搜索树_原创 | 好端端的数据结构,为什么叫它SB树呢?...
  8. Hadoop集群(四) Hadoop升级
  9. c++:多线程的创建和unique_lock<mutex>的使用
  10. oralce中的dual详解
  11. 计算机网络安全基础知识复习
  12. 富文本 和 图片裁切
  13. TSC打印机使用教程终极版(转)
  14. 你的死工资,正在拖垮你一辈子需要花多少钱
  15. Java求一元二次方程的根
  16. HNUST 辅导上机(模拟)
  17. 西南科技大学Linux实验名称:实验二 Linux环境网络管理
  18. 天府一品 茶叶商城平台 uni app 开发总结 H5商城
  19. dataGrip导出sql脚本
  20. FL Studio 20.9水果最高版 完美使用中文全部功能

热门文章

  1. QWidget中加载QML页面并设置透明背景
  2. win10光驱位连接计算机,windows10不能识别光驱位硬盘
  3. matlab信息隐藏算法,实验四--基于DCT域的信息隐藏算法
  4. div中插入图片_Web前端开发基础知识,设置网页背景图,如何在网页中插入图片...
  5. c/c++ / printf 实现
  6. oracle表 游标,Oracle游标表达式和表函数
  7. python中二维数组如何按索引找元素_按索引或坐标访问二维数组中的元素
  8. mysal向一个无法连接的网络尝试了一个套接字操作 0.0.3.235_第十二章 Java网络编程(3)——套接字(上)...
  9. 有监督学习和无监督学习举例_对比自监督学习
  10. python程序练习题第三章_python核心编程-第三章-习题