全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

详解Android类加载ClassLoader

基本知识

Java的类加载设计了一套双亲代理的模式,使得用户没法替换系统的核心类,从而让应用更安全。所谓双亲代理就是指,当加载类的时候首先去Bootstrap中加载类,如果没有则去Extension中加载,如果再没有才去AppClassLoader中去加载。从而实现安全和稳定。

Java ClassLoader

BootstrapClassLoader

引导类加载器 ,用来加载Java的核心库。通过底层代码来实现的,基本上只要parent为null,那就表示引导类加载器。

比如:charsets.jar、deploy.jar、javaws.jar、jce.jar、jfr.jar、jfxswt.jar、jsse.jar、management-agent.jar、plugin.jar、resources.jar、rt.jar

ExtClassLoader

拓展类加载器 ,用来加载Java的拓展的类库, ${JAVA_HOME}/jre/lib/ext/ 目录中的所有jar。

比如:cldrdata.jar、dnsns.jar、jfxrt.jar、localedata.jar、nashorn.jar、sunec.jar、sunjce_provider.jar、sunpkcs11.jar、zipfs.jar等等

AppClassLoader

系统类加载器 (不要被名字给迷惑),用来加载Java应用中的类。一般来说自己写的类都是通过这个加载的。而Java中 ClassLoader.getSystemClassLoader() 返回的就是AppClassLoader。(Android中修改了ClassLoader的逻辑,返回的会是一个PathClassLoader)

自定义ClassLoader

用户如果想自定义ClassLoader的话,只需要继承自 java.lang.ClassLoader 即可。

ClassLoader中与加载类相关的方法:

  1. getParent() 返回该类加载器的父类加载器。
  2. loadClass(String name) 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。
  3. findClass(String name) 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。
  4. findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。
  5. defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。

也许你不太了解上面几个函数的区别,没关系,我们来看下源码是如何实现的。

//ClassLoader.java
protected Class<?> loadClass(String name, boolean resolve)
  throws ClassNotFoundException
{
    // 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
      }
    }
    return c;
}

所以优先级大概如下:

loadClass → findLoadedClass → parent.loadClass/findBootstrapClassOrNull → findClass → defineClass

Android ClassLoader

在Android中ClassLoader主要有两个直接子类,叫做 BaseDexClassLoader 和 SecureClassLoader 。而前者有两个直接子类是 PathClassLoader 和 DexClassLoader (Android O添加了 InMemoryDexClassLoader ,略)。

我们只讨论PathClassLoader和DexClassLoader

PathClassLoader

用来加载安装了的应用中的dex文件。它也是Android里面的一个最核心的ClassLoader了。相当于Java中的那个AppClassLoader。

public class PathClassLoader extends BaseDexClassLoader {
  /**
   * Creates a {@code PathClassLoader} that operates on a given list of files
   * and directories. This method is equivalent to calling
   * {@link #PathClassLoader(String, String, ClassLoader)} with a
   * {@code null} value for the second argument (see description there).
   *
   * @param dexPath the list of jar/apk files containing classes and
   * resources, delimited by {@code File.pathSeparator}, which
   * defaults to {@code ":"} on Android
   * @param parent the parent class loader
   */
  public PathClassLoader(String dexPath, ClassLoader parent) {
    super(dexPath, null, null, parent);
  }

  /**
   * Creates a {@code PathClassLoader} that operates on two given
   * lists of files and directories. The entries of the first list
   * should be one of the following:
   *
   * <ul>
   * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as
   * well as arbitrary resources.
   * <li>Raw ".dex" files (not inside a zip file).
   * </ul>
   *
   * The entries of the second list should be directories containing
   * native library files.
   *
   * @param dexPath the list of jar/apk files containing classes and
   * resources, delimited by {@code File.pathSeparator}, which
   * defaults to {@code ":"} on Android
   * @param librarySearchPath the list of directories containing native
   * libraries, delimited by {@code File.pathSeparator}; may be
   * {@code null}
   * @param parent the parent class loader
   */
  public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
    super(dexPath, null, librarySearchPath, parent);
  }
}

它的实例化是通过调用 ApplicationLoaders.getClassLoader 来实现的。

它是在ActivityThread启动时发送一个BIND_APPLICATION消息后在handleBindApplication中创建ContextImpl时调用LoadedApk里面的 getResources(ActivityThread mainThread) 最后回到ActivityThread中又调用LoadedApk的 getClassLoader 生成的,具体的在LoadedApk的 createOrUpdateClassLoaderLocked

那么问题来了,当Android加载class的时候,LoadedApk中的ClassLoader是怎么被调用到的呢?

其实Class里面,如果你不给ClassLoader的话,它默认会去拿Java虚拟机栈里面的 CallingClassLoader ,而这个就是LoadedApk里面的同一个ClassLoader。

//Class.java
public static Class<?> forName(String className)
      throws ClassNotFoundException {
  return forName(className, true, VMStack.getCallingClassLoader());
}

查看VMStack的源码发现 getCallingClassLoader 其实是一个native函数,Android通过底层实现了这个。

//dalvik.system.VMStack
/**
 * Returns the defining class loader of the caller's caller.
 *
 * @return the requested class loader, or {@code null} if this is the
 *     bootstrap class loader.
 */
@FastNative
native public static ClassLoader getCallingClassLoader();

底层想必最终也是拿到LoadedApk里面的ClassLoader。

DexClassLoader

它是一个可以用来加载包含dex文件的jar或者apk文件的,但是它可以用来加载非安装的apk。比如加载sdcard上面的,或者NetWork的。

public class DexClassLoader extends BaseDexClassLoader {
  /**
   * Creates a {@code DexClassLoader} that finds interpreted and native
   * code. Interpreted classes are found in a set of DEX files contained
   * in Jar or APK files.
   *
   * <p>The path lists are separated using the character specified by the
   * {@code path.separator} system property, which defaults to {@code :}.
   *
   * @param dexPath the list of jar/apk files containing classes and
   *   resources, delimited by {@code File.pathSeparator}, which
   *   defaults to {@code ":"} on Android
   * @param optimizedDirectory directory where optimized dex files
   *   should be written; must not be {@code null}
   * @param librarySearchPath the list of directories containing native
   *   libraries, delimited by {@code File.pathSeparator}; may be
   *   {@code null}
   * @param parent the parent class loader
   */
  public DexClassLoader(String dexPath, String optimizedDirectory,
      String librarySearchPath, ClassLoader parent) {
    super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
  }
}

比如现在很流行的插件化/热补丁,其实都是通过DexClassLoader来实现的。具体思路是: 创建一个DexClassLoader,通过反射将前者的DexPathList跟系统的PathClassLoader中的DexPathList合并,就可以实现优先加载我们自己的新类,从而替换旧类中的逻辑了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# classloader  # 加载类  # 加载  # 动态加载  # Android源码探究之BaseDexClassLoader的使用  # 关于Android中自定义ClassLoader耗时问题的追查  # 浅谈Android Classloader动态加载分析  # Android开发中类加载器DexClassLoader的简单使用讲解  # Android类加载ClassLoader双亲委托机制详解  # 都是  # 是一个  # 来实现  # 结果是  # 子类  # 自定义  # 自己的  # 几个  # 如果你  # 有两个  # 是在  # 来了  # 那就  # 不太  # 是怎么  # 它是  # 如果没有  # 它可以  # 只需要 


相关文章: css网站制作参考文献有哪些,易聊怎么注册?  建站之星3.0如何解决常见操作问题?  如何安全更换建站之星模板并保留数据?  ,购物网站怎么盈利呢?  如何用PHP快速搭建高效网站?分步指南  如何正确下载安装西数主机建站助手?  网站网页制作专业公司,怎样制作自己的网页?  如何获取PHP WAP自助建站系统源码?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  h5网站制作工具有哪些,h5页面制作工具有哪些?  如何在橙子建站中快速调整背景颜色?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  制作证书网站有哪些,全国城建培训中心证书查询官网?  重庆市网站制作公司,重庆招聘网站哪个好?  如何通过FTP空间快速搭建安全高效网站?  常州企业网站制作公司,全国继续教育网怎么登录?  Swift中swift中的switch 语句  视频网站制作教程,怎么样制作优酷网的小视频?  如何通过.red域名打造高辨识度品牌网站?  个人网站制作流程图片大全,个人网站如何注销?  网站app免费制作软件,能免费看各大网站视频的手机app?  建站为何优先选择香港服务器?  如何在西部数码注册域名并快速搭建网站?  盐城做公司网站,江苏电子版退休证办理流程?  如何在Golang中使用replace替换模块_指定本地或远程路径  北京网站制作网页,网站升级改版需要多久?  小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建  香港服务器网站推广:SEO优化与外贸独立站搭建策略  如何选择适配移动端的WAP自助建站平台?  建站之星如何快速生成多端适配网站?  ppt制作免费网站有哪些,ppt模板免费下载网站?  广州营销型建站服务商推荐:技术优势与SEO优化解析  台州网站建设制作公司,浙江手机无犯罪记录证明怎么开?  建站之星代理如何优化在线客服效率?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  武汉外贸网站制作公司,现在武汉外贸前景怎么样啊?  建站之星手机一键生成:多端自适应+小程序开发快速建站指南  ,南京靠谱的征婚网站?  想学网站制作怎么学,建立一个网站要花费多少?  网站制作知乎推荐,想做自己的网站用什么工具比较好?  网站制作费用多少钱,一个网站的运营,需要哪些费用?  如何解决ASP生成WAP建站中文乱码问题?  昆明网站制作哪家好,昆明公租房申请网上登录入口?  如何在IIS管理器中快速创建并配置网站?  PHP 500报错的快速解决方法  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  如何选择网络建站服务器?高效建站必看指南  如何高效生成建站之星成品网站源码?  网站制作免费,什么网站能看正片电影? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。