记录学习java 加载器学习所获心得,逐步记录了解java加载器的过程。为了知悉android 插件化的实现原理,从而需要从头了解android加载apk,以及基础的java类加载的加载过程情况,为方便记录和记忆,故此将学习了解的过程记录成文字,以下文字记录部分可能来自与多个来源,主体以Java源码和IBM开发者博客有关java加载技术的博客为主。

Java 类的加载过程

惯性思维,想要了解apk的加载过程,我希望先简单知道以下Java中对类加载过程的处理(Java一直都是android的官方开发语言,虽然现在kotlin也是,但原理不变)。首先需要了解Java 类在jvm中的加载过程,基本的流程如下:

  • 装载

    装载是通过已经编译生成的class文件的位置查找文件获取其字节流导入class文件,并将其转换成一个Class类的一个实例,将类的实例存放在jvm的堆区,获取装载类的信息到方法区(属于jvm的内存区域的一种,主要用于存放类的字段、方法,常量池等信息),这里就是负责处理完成类的加载的过程,主要是由ClassLoader及其子类完成。

  • 链接

    其主要功能就是对类信息格式进行校验,分配方法区域的类变量的初始值(并非设置的初始化数值,而是初始“0”值)并将类的引用指向对应类的实例。其内部分为三个过程:校验 —>准备—>解析。执行顺序为既定的。

  • 初始化

    初始化类的静态变量和静态代码块(相对于链接中的准备阶段,将已经“初始化”的静态数据进行真正的初始化).类的初始化情况:

    1)遇到类的创建指令New指令

    2)java主运行程序的入口类的实例

    3)通过反射创建类(newInstance、forClass等)

    4)子类初始化触发父类的初始化操作

    5)java 1.7动态类型初始化

  • 使用和卸载

    对创建java对象的操作以及java回收机制对jvm的自动回收卸载。

Java 类加载器

如上,对于java类的加载使用,属于应用层程序员可控过程就只有类的加载过程,通过指定类的加载器来加载我们的类信息,首先通过java的源码文档来简单了解一下类加载的介绍。类加载器位置:

java.lang.ClassLoader.java

文档介绍为:类加载器主要负责加载类的对象,通过给定一个类的“二进制名称”,那么类加载器会尝试定位或身成类定义的数据信息。一般策略是将二进制名称转化为一个文件的名称并加载该类文件的二进制数据。数组类型的类的对象并不是由类加载器创建,而是java 运行时根据需要自动创建.数组类型的加载器由Class.getClassLoader()返回.该加载器与其元素类型的类加载器是相同的;如果该元素类型是基本类型,则该数组类没有类加载器。

程序可以通过继承ClassLoader的子类来扩展动态加载方式.类加载器支持双亲委托模型(通过委托父类查找资源的方式进行操作)查找类或类的资源.虚拟机的内置类加载器(称为 “bootstrap class loader”)本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器……

如上,为部分对于ClassLoader的介绍文字.对于通用类加载器通常将其分为四个类型,如下介绍:

  • 引导型类加载器(bootstrap)

    该类加载器并没有父类类加载器,具体实现是通过原生代码实现(平台相关的),用于加载Java的核心代码,无法直接通过代码使用.

  • 扩展型类加载器

    它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。android中相当于java.lang.BootClassLoader

  • 系统类加载器(system class loader)

    它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()获取。android 中相当与dalvik.system.PathClassLoader.

  • 线程上下文类加载器

    用于设置和获取线程上下文的类加载器,若是未曾设置该加载器,线程上下文类加载器将继承自父线的上下文类加载器,而Java应用初始线程上下文类加载器为系统加载器,android中也就是继承自BaseDexClassLoader的子类加器PathClassLoader或者DexClassLoader加载器.

    基于Android 平台对于以上的加载器做一个简单的代码测试如下:


var loader=classLoader
while (loader != null) {
println("加载器类型:${loader.toString()}")
loader = loader.parent
} //输出结果如下 10-30 17:55:05.964 23338-23338/com.enjoytoday I/System.out: 加载器类型:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.enjoytoday-2/base.apk", zip file "/data/app/com.enjoytoday-2/split_lib_dependencies_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_0_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_1_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_2_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_3_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_4_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_5_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_6_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_7_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_8_apk.apk", zip file "/data/app/com.enjoytoday-2/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.enjoytoday-2/lib/arm64, /system/fake-libs64, /data/app/com.enjoytoday-2/base.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_dependencies_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_0_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_1_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_2_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_3_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_4_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_5_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_6_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_7_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_8_apk.apk!/lib/arm64-v8a, /data/app/com.enjoytoday-2/split_lib_slice_9_apk.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64, /system/vendor/lib64, /product/lib64]]]
10-30 17:55:05.964 23338-23338/com.enjoytoday I/System.out: 加载器类型:java.lang.BootClassLoader@d725e7d

Android 中的类加载器

Android 中的虚拟机是由dalvik来实现,dalvik并非典型的Java虚拟机。因此,其类的加载器和标准有所不同,对于dalvik而言,其并不可以直接识别加载class文件,而是对class打包成的dex文件进行加载。因此,Android源码对ClassLoader进行处理,并派生一个子类BaseDexClassLoader,其本质类似于jvm中的ClassLoader,确切的说可以说是一个Dex加载器。

基于Android 平台的类加载器结构如下:

  • BootClassLoader

    是属于ClassLoader的一个内部类,不可直接使用,每个ClassLoader中都存在一个parent(ClassLoader类型),父类加载器,而BootClassLoader属于最顶层的parent.

  • URLClassLoader

    这个是一个输入jar的加载器,在java中支持在线或本地指定jar文件来加载jar包,但由于android中dalvik并不可以识别class或者jar,只能加载dex,所以并不可以直接使用URLClassLoader来加载jar文件

  • BaseDexClassLoader

这个属于加载dex文件的加载器的实现,具体的加载逻辑在其中实现

  • PathClassLoader

    继承自BaseDexClassLoader,为默认apk安装使用的类加载器,会自动寻址apk安装后默认解压后的dex路径,目前dalvik并不支持使用PathClassLoader来加载未安装的apk,但也有文章说art可以实现,暂未验证,不能确认。

  • DexClassLoader

    继承自BaseDexClassLoader,可以直接加载dex,压缩文件(apk文件),jar文件,是实现android插件化一个重要的元素,可以帮我们完成对为安装的插件apk的加载过程.

android基本加载知识记录,已留备存。

Enjoytoday,EnjoyCoding

Android插件基础之类加载器学习的更多相关文章

  1. 黑马程序员:Java基础总结----类加载器

    黑马程序员:Java基础总结 类加载器   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个 ...

  2. Java基础之类加载器

    Java类加载器是用户程序和JVM虚拟机之间的桥梁,在Java程序中起了至关重要的作用,理解它有利于我们写出更优雅的程序.本文首先介绍了Java虚拟机加载程序的过程,简述了Java类加载器的加载方式( ...

  3. java类加载器学习2——自定义类加载器和父类委托机制带来的问题

    一.自定义类加载器的一般步骤 Java的类加载器自从JDK1.2开始便引入了一条机制叫做父类委托机制.一个类需要被加载的时候,JVM先会调用他的父类加载器进行加载,父类调用父类的父类,一直到顶级类加载 ...

  4. tomcat 7 中的类加载器学习

    tomcat 7自带很多junit测试用例,可以帮助我们窥探源码的秘密.以下使用来测试类加载器的一个测试用例.类加载器也是对象,他们用来将类从类从.class文件加载到虚拟机,这些已经讲了很多,深入j ...

  5. java基础之—类加载器

    要了解类加载器先要了解类的加载 一.类的加载(类的加载概述) 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 1.加载 就是指将clas ...

  6. Java类加载器学习笔记

    今后一段时间会全面读一下<深入理解Java虚拟机> 在这里先记一下在网上看到的几篇介绍 类加载器 的文章,等读到虚拟机类加载机制再详细介绍. 超详细Java中的ClassLoader详解 ...

  7. Java基础加强-类加载器

    /*类加载器*/ 把.class文件从硬盘上加载出来,将类的字节码(二进制)加载到内存中 /*类加载器及其委托机制*/ Java虚拟机中可以安装多个类加载器(可以自己编写),系统默认三个主要类加载器, ...

  8. JAVA基础_类加载器

    什么是类加载器 类加载器是Java语言在1.0版本就引入的.最初是为了满足JavaApplet需要.现在类加载器在Web容器和OSGI中得到了广泛的应用,一般来说,Java应用的开发人员不需要直接同类 ...

  9. java 基础之--类加载器的过程

    先来段代码,大家瞧瞧运行pritln的结果是什么?(认真想一想哦

随机推荐

  1. 矩阵解压,网络流UESTC-1962天才钱vs学霸周2

    天才钱vs学霸周2 Time Limit: 500 MS     Memory Limit: 128 MB Submit Status 由于上次的游戏中学霸周输了,因此学霸周想出个问题为难天才钱,问题 ...

  2. WebAPI之postman变量和session/token

    postman使用变量: 之前我们请求里面的主机地址都是localhost,表示本机.而在实际测试过程中,服务器地址往往并非是在本机上的,这时候就需要用到变量. postman支持多个测试环境,一个环 ...

  3. 笔记||Python3之函数

    函数:          函数的概念:就是一段代码:一段操作流程. 优点:代码量少.简洁.   维护起来方便 -- 在函数的定义进行修改 函数的定义:1 - def 函数名(): 函数内容 2 - 函 ...

  4. 小白进阶之路—python脚本(1)判断是否是一个目录

    #!/usr/bin/env python# -*- coding: utf-8 -*-import os   dir = "/var/www/html/EnjoyWeekend/" ...

  5. BIOS安全设置

    1.开机按F2进入BIOS 2.进入 Security 界面 3.Set user password 用户密码 开机密码 设置为123456 4.Set supervisor password 进BI ...

  6. docker-compose部署

    一.部署compose docker compose可以方便我们快捷高效地管理容器的启动.停止.重启等操作,它类似于linux下的shell脚本,基于yaml语法,在该文件里我们可以描述应用的架构,比 ...

  7. Wireshark数据包分析入门

    Wireshark数据包分析(一)——使用入门   Wireshark简介: Wireshark是一款最流行和强大的开源数据包抓包与分析工具,没有之一.在SecTools安全社区里颇受欢迎,曾一度超越 ...

  8. UWP 使用SSL证书,保证数据安全

    事情是这样的,我们后端的小伙伴升级了用户会员系统,使用了全新的GraphQL登录机制,并且采用SSL加密的方式来实现阻止陌生客户端请求的案例. GraphQL在UWP端的实现,以后有时间会单独写一篇文 ...

  9. Ubuntu虚拟机安装VMware Tools

    前言 在用VMware安装好Linux虚拟机后,发现在虚拟机下安装的Ubuntu16.04 64位无法进入全屏模式,同时存在物理机和虚拟机之间无法实现文件传输的问题,通过安装VMware Tools得 ...

  10. 《Java基础知识》Java数据类型以及变量的定义

    Java 是一种强类型的语言,声明变量时必须指明数据类型.变量(variable)的值占据一定的内存空间.不同类型的变量占据不同的大小. Java中共有8种基本数据类型,包括4 种整型.2 种浮点型. ...