精华内容
下载资源
问答
  • ClassLoader加载原理

    2016-03-12 11:09:05
    总结:先由父装载器来寻找引用类,如果没有找到,再由本类的加载器来加载引用类;
    总结:先由父装载器来寻找引用类,如果没有找到,再由本类的加载器来加载引用类;
    展开全文
  • JDK之ClassLoader加载原理


    在这里插入图片描述

    1.官网

    https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
    在这里插入图片描述
    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html
    在这里插入图片描述

    2.整体流程

    2.1.Loading

    2.1.1.找到class所在的目录和文件

    2.1.1.1.JDK中有一个类叫ClassLoader.findClass(className),帮忙我们寻找和加载类

    在这里插入图片描述

    2.1.1.2.不同的ClassLoader加载顺序图解

    在这里插入图片描述

    加载的顺序:加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
              从Custom ClassLoader到BootStrap ClassLoader逐层检查,
              只要某个Classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次
    
    2.1.2.2.1.双亲委派模式加载
    2.1.2.2.1.1.定义
    如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把
    这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就
    成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
    
    2.1.2.2.1.2.优势
    Java类随着加载它的类加载器一起具备了一种带有优先级的层次关系。比如,Java中的
    Object类,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型
    最顶端的启动类加载器进行加载,因此Object在各种类加载环境中都是同一个类。如果不采用
    双亲委派模型,那么由各个类加载器自己取加载的话,那么系统中会存在多种不同的Object类。
    

    通俗理解

    比如不同的层级的classloader中有多个java.lang.Example.class类,这样会产生冲突;
    这样先有上到下的去加载,其实就很好地避免了这个重复的问题
    
    2.1.2.2.1.3.如何破坏这种模式
    1.我们在ClassLoader.findClass(className)方法中,其实我们也可以看到,也是先去父加载器里面去加载
    2.可以继承ClassLoader类,然后重写其中的loadClass方法,其他方式大家可以自己了解拓展一下。
    

    在这里插入图片描述

    2.1.2.将找到class文件加载到JVM中

    2.1.2.1.概述

    1.关于我们的class文件如何在JVM虚拟机中存储这一块,我们肯定不能全部直接放到JVM中,因为有一些东西是公用的,有一些东西跟我们每一次请求的
      线程资源数据相关的,所以如何高效的利用存储JVM内存空间,就涉及到我们如何存储CLass文件
    2.JVM对于class文件的存储时分块存储;
      关于内存中的块,我们也可以参考官网的地址;
    

    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5

    在这里插入图片描述

    2.1.2.2.class文件在JVM中的存储分区问题介绍

    https://blog.csdn.net/u014636209/article/details/104400529

    2.2.Linking

    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4
    在这里插入图片描述

    2.2.1.Verification [验证]

    1.这里的验证主要是我们上面加载过来的class(二进制文件类或者接口)格式(structrue)的一个验证;
    2.同时,会加载这个class依赖的其他的class(二进制文件类或者接口),这里注意下,这里不会验证这些加载进来的类的格式;
    

    之所以不验证依赖的文件,主要是因为,我们每一个文件都会加载,所以没有必要再加载的时候,再次验证!
    在这里插入图片描述

    2.2.2.Preparation [准备]

    1.为静态变量初始化内存空间
    2.为静态变量初始化值
    3.比如static int =10; 这一行在初始化的时候,是初始化值为0
    

    在这里插入图片描述

    2.2.3.Resolution [解析]

    1.将符号引用转变为直接引用;
    

    我们知道classFile的结构如下

    1.下面的一些标示实际上只是一个符号引用,这里将符号引用指向为直接引用JVM内存中的实际地址;
    
    ClassFile {
        u4             magic;  #文件类型
        u2             minor_version; # jdk版本
        u2             major_version; # jdk版本
        u2             constant_pool_count; # 常量的个数
        cp_info        constant_pool[constant_pool_count-1];
        u2             access_flags;
        u2             this_class;  #本类的引用
        u2             super_class; #父类的引用
        u2             interfaces_count;#接口数量
        u2             interfaces[interfaces_count];
        u2             fields_count; # 字段个属于
        field_info     fields[fields_count];
        u2             methods_count; #方法个数
        method_info    methods[methods_count];
        u2             attributes_count;
        attribute_info attributes[attributes_count];
    }
    

    下面是一个App.class的二进制文件(16进制)

    cafe babe 0000 0034 001d 0a00 0600 0f09
    0010 0011 0800 120a 0013 0014 0700 1507
    0016 0100 063c 696e 6974 3e01 0003 2829
    5601 0004 436f 6465 0100 0f4c 696e 654e
    756d 6265 7254 6162 6c65 0100 046d 6169
    6e01 0016 285b 4c6a 6176 612f 6c61 6e67
    2f53 7472 696e 673b 2956 0100 0a53 6f75
    7263 6546 696c 6501 0008 4170 702e 6a61
    7661 0c00 0700 0807 0017 0c00 1800 1901
    000c 4865 6c6c 6f20 576f 726c 6421 0700
    1a0c 001b 001c 0100 1563 6f6d 2f67 616f
    7869 6e66 752f 6465 6d6f 2f41 7070 0100
    106a 6176 612f 6c61 6e67 2f4f 626a 6563
    7401 0010 6a61 7661 2f6c 616e 672f 5379
    7374 656d 0100 036f 7574 0100 154c 6a61
    7661 2f69 6f2f 5072 696e 7453 7472 6561
    6d3b 0100 136a 6176 612f 696f 2f50 7269
    6e74 5374 7265 616d 0100 0770 7269 6e74
    6c6e 0100 1528 4c6a 6176 612f 6c61 6e67
    2f53 7472 696e 673b 2956 0021 0005 0006
    0000 0000 0002 0001 0007 0008 0001 0009
    0000 001d 0001 0001 0000 0005 2ab7 0001
    b100 0000 0100 0a00 0000 0600 0100 0000
    0700 0900 0b00 0c00 0100 0900 0000 2500
    0200 0100 0000 09b2 0002 1203 b600 04b1
    0000 0001 000a 0000 000a 0002 0000 000b
    0008 000c 0001 000d 0000 0002 000e 
    

    2.3.Initialization [初始化]

    1.为静态变量进行初始化赋值,比如:static int =10; 开始设置值为10
    
    展开全文
  • classloader加载原理

    2011-07-05 10:07:59
    转载 http://www.iteye.com/topic/98178
    展开全文
  • 前言ClassLoader类加载,是动态加载机制及现在火热的插件化机制中很基础但同时又很重要的知识点,通过学习这一章节,能在脑海中浮现出Android系统、应用的加载原理整个框架。什么是ClassLoader翻译过来就是类加载器...

    前言

    ClassLoader类加载,是动态加载机制及现在火热的插件化机制中很基础但同时又很重要的知识点,通过学习这一章节,能在脑海中浮现出Android系统、应用的加载原理整个框架。

    什么是ClassLoader

    翻译过来就是类加载器,见名知义。类在生成字节码.class文件后,从物理文件地址加载到Dalvik/ART虚拟机中使用。

    Android中的类体现

    这里会提到Android中使用较多的两种ClassLoader,当然还有属于JVM的ClassLoader,有兴趣的可以自行查阅。

    BootClassLoader: Dalvik/ART虚拟机用于加载Android系统类的Loader,应用层通过获取父ClassLoader的最终项。

    PathClassLoader: 我们知道,打包APK后实际上是把java文件都生成dex文件,而这个Loader就是在应用启动时,加载已安装APK的dex文件。

    DexClassLoader: 常见的动态加载机制都用这个类,传入指定路径加载指定dex文件。

    加载原理

    ClassLoader使用的是双亲委托机制。双亲委派模型,旨在于让顶级父类加载器先加载类,若不成功,则一层层往下加载,最终到当前加载器。这样做的目的是保持类加载系统的稳定性,不会出现不同加载器加载同一个类时,出现多个类实例。

    4c1b0924a14f

    Android-ClassLoader加载机制.png

    类加载源码解析

    关注ClassLoader的loadClass方法

    BootClassLoader用于加载系统层的类,比较特殊,loadClass查询虚拟机中没有缓存时最终会调用到findClass ——> Native 方法 Class.classForName:

    4c1b0924a14f

    BootClassLoader-findClass.png

    其余的loadClass都是调用到下图中,先查找当前loader是否有加载到该类的缓存,若没有,就获取父加载器查找,递归直到父加载器不存在。

    因此总体来看这是一个先向上委托父加载器,再向下查找的过程。若查询为null,将从当前加载器加载类,最终会调用loadClass方法,加载成功就跳出递归。

    4c1b0924a14f

    ClassLoader-loadClass.png

    DexClassLoader和PathClassLoader 都是继承于BaseDexClassLoader,从构造方法可知,optimizedDirectory这个参数已经无效了,因为已经没有向下传递的,我们一起直接看看它的findClass方法。

    4c1b0924a14f

    BaseDexClassLoader.png

    4c1b0924a14f

    BaseDexClassLoader-findclass.png

    实际上调用的是DexPathList.findClass方法,这里有个dexElements,看看他是如何构造出来的。

    4c1b0924a14f

    DexPathList-findClass.png

    根据我们创建ClassLoader时,传入的dexPath,支持APK、DEX、JAR文件全路径,以/分隔符分开。分别调用loadDexFile,这就是我们生成最终可用的dex文件的过程。最终构造出dexElements。

    4c1b0924a14f

    DexPathList-makePathElements.png

    4c1b0924a14f

    DexFile-loadDexFile.png

    最终调用loadClassBinaryName,这个方法最终会调到底层Native 方法DextFile.defineClassNative。

    4c1b0924a14f

    DexFile-loadClassBinaryName.png

    4c1b0924a14f

    DexFile-defineClassNative.png

    根据以上的加载原理,已经能大致了解Android类加载的过程。就是我们使用DexClassLoader或PathClassLoader加载类时,系统究竟做了什么,也是能有个印象,为我们接下来更加深入到类加载器在虚拟机中是如何运行的知识点建立一个基础。

    使用方式

    DexClassLoader 构造方法参数说明

    4c1b0924a14f

    DexClassLoader.png

    参数名

    描述

    dexPath

    待提取dex的文件全路径,多个时以 ":" 分隔符(在Android中以File.pathSeparator定义)隔开

    optimizedDirectory

    提取到dex文件后存放文件夹路径,但现在已经无效了

    libraryPath

    so文件所在文件夹路径, 多个时以 ":" 分隔符(在Android中以File.pathSeparator定义)隔开

    parent

    父classloader

    举个例子吧

    本地项目新建一个系统已实现类 —— TextUtils.java,其中的isEmpty的方法体实现变更,项目中能否调用到我更改后的方法逻辑呢?

    4c1b0924a14f

    TextUtils.png

    4c1b0924a14f

    checkTextUtils.png

    答案显而易见是不可以的,前面我们学到,类加载委托是从下至上,类查找是从上至下的,顶级类加载器父类BootClassloader查找到TextUtils时,会首先把类加载入缓存。级别更低的ClassLoader均从缓存获取成功,因此项目中使用PathClassloader才能加载到的TextUtils是无法成功的。

    4c1b0924a14f

    checkTextUtils-result.png

    用DexClassLoader的方式加载外部dex文件,首先新建类Dextest用于打包并使用dx工具生成dextest.jar放在外部扩展文件夹dx/下。接着构建DexClassLoader并反射触发即可成功。

    4c1b0924a14f

    Dextest.png

    4c1b0924a14f

    loadExternDex.png

    4c1b0924a14f

    loadExternDex-result.png

    总结

    我们若想了解各种加载流程,还是需要多深入源码,Android-ClassLoader实现逻辑算是非常清晰易懂,但对我们日常开发如插件化方案会有非常大的帮助。

    阅读源码由于各模块代码体量都是不小的,为了效率应该挑重点看,也可以结合博客加快自己看源码的进程。

    native底层代码阅读:

    展开全文
  • Android ClassLoader加载过程源码分析

    多人点赞 2019-07-15 17:27:36
    背景 Android开发过程中,开发的小伙伴对动态加载代码肯定不陌生,在使用各个开源框架的过程中都应该有接触...详细分析ClassLoader加载原理 ClassLoader 的继承关系如下: 这里我们主要分析一下 BaseDexClassLo...
  • 【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!
  • Java类加载器 — classloader原理及应用

    千次阅读 多人点赞 2021-02-19 16:20:00
    什么是classloaderclassloader顾名思义,即是类加载。虚拟机把描述类的数据从class字节码文件加载到内存,并对数据进行检验、转换解析和初始化,最终形成可以被虚拟机直接使...
  • 在Spring Boot的嵌入式Web容器原理一节中,我们已经介绍了Spring Boot对Tomcat容器的加载过程,本节我们进一步讲解SpringBoot的ClassLoader加载机制。 熟悉Tomcat工作原理的人应该知道,Tomcat内部实现了自定义的类...
  • 初始化二、什么是 ClassLoaderClassLoader 作用:1、ClassLoader 类结构分析2.ClassLoader 的等级加载机制3.ClassLoader加载类的原理三、同名类加载顺序总结 前言 在本地domain的一次更新jar包之后,本地的某个...
  • 上一章节中,讲了如何通过ClassLoader加载dex文件,调用插件中的代码,链接:...加载原理 在上一章节中,已经讲过,ClassLoader加载类是通过loadClass方法加载类文件的: Class<?> clz = dexClassLoader.lo...
  • ClassLoader加载机制和原理详解
  • 文章引用: ... 一 采用双亲委托机制加载类过程 Java中ClassLoader加载采用了双亲委托机制,采用双亲委托...当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载...
  • 主要介绍了深入Spring Boot之ClassLoader的继承关系和影响,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 深入分析Java ClassLoader原理

    万次阅读 多人点赞 2012-02-25 21:39:24
    一、什么是ClassLoader?  大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的...
  • 一 前言介绍 从16年开始开始,热修复技术在 Android 技术社区热了一阵,这种不用发布...学习热修复技术是安卓开发者进阶必不可少的一条道路之一,而热修复的核心就是:java类加载机制。 1.1 ART 和 Dalvik DVM是...
  • 接着上篇我们这一篇说ClassLoader及dex加载过程。为了解决65535这个问题,Google提出了multidex方案,即一个apk文件可以包含多个dex文件。 不过值得注意的是,除了第一个dex文件以外,其他的dex文件都是以资源的...
  • class加载过程: 1.loading 1.双亲委派,主要出于安全考虑 2.ClassLoader 的源码 findInCache -> parent.loadClass -> findClass() 3.自定义类加载器 1.继承ClassLoader 2.重写 findClass() 方法...
  • classLoader加载机制分析和案例剖析.
  • 关于ClassLoader原理

    千次阅读 2017-12-12 11:21:25
    1. Class文件的加载过程 Java虚拟机类加载过程是把Class类文件加载到内存,并对Class文件中的数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型的过程。 在加载阶段,java虚拟机需要完成以下...
  • ClassLoader双亲委派机制 类加载加载类步骤: 首先会自底向上检测是否加载过此Class(即在缓存区中是否有此Class),如果有直接返回Class对象; 判断父加载器是否存在,如果存在父加载器,则请求父类加载器来...
  • android动态加载ClassLoader机制

    千次阅读 2017-04-22 18:02:00
    平时做开发有时会导入第三方jar包, 在运行程序时首先需要将apk对应的类加载到内存中, 动态加载是指加载动态库以及jar包等。 Android的Dalvik/ART虚拟机如同标准JAVA的JVM虚拟机一样,在运行程序时首先需要将对应的...
  • 参考: ClassLoader原理总结 ...   图解classloader加载class的流程及自定义ClassLoader http://lshirley2009.javaeye.com/blog/486133 JAVA 类加载 http://blo
  • ClassLoader加载机制深入分析

    千次阅读 2018-04-11 20:42:40
    在程序运行的时候是需要将这些class文件加载到内存中才能被我们使用的,而且这些class文件也不是一次性的被加载进内存的,它是什么时候需要就什么时候加载加载这些class文件到内存中就需要使用ClassLoader加载器...
  • 本篇文章主要给大家讲述了Java中ClassLoader加载原理以及用法总结,一起学习下。
  • ClassLoader加载机制

    2017-09-08 17:13:17
    该电子书详细介绍了java虚拟机类加载机制,对于深入理解jvm工作原理有很好的帮助作用,对于初学java,有一定工作经验的小伙伴来说是一本提高自身java素养,夯实自己java基本技能的“葵花宝典”。
  • 不管是android 还是java项目我们知道我们的java文件都会通过 javac命令编译成二进制class文件,然后虚拟机再通过classloader类对class文件进行加载生成Class对象。其中java 和 android的classloader实现上还是有区别...
  • classloader加载原理

    2010-04-13 15:24:00
    JVM在运行时会产生三个ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader.其中,Bootstrap是用C++编写的,我们在Java中看不到它,是null。它用来加载核心类库,在JVM源代码中这样写道:...
  • java应用环境中不同的class分别由不同的ClassLoader负责加载。一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职: Bootstrap ClassLoader 负责加载...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,519
精华内容 19,807
关键字:

classloader加载原理