Android插件基础之类加载器学习
记录学习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基本加载知识记录,已留备存。
Android插件基础之类加载器学习的更多相关文章
- 黑马程序员:Java基础总结----类加载器
黑马程序员:Java基础总结 类加载器 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个 ...
- Java基础之类加载器
Java类加载器是用户程序和JVM虚拟机之间的桥梁,在Java程序中起了至关重要的作用,理解它有利于我们写出更优雅的程序.本文首先介绍了Java虚拟机加载程序的过程,简述了Java类加载器的加载方式( ...
- java类加载器学习2——自定义类加载器和父类委托机制带来的问题
一.自定义类加载器的一般步骤 Java的类加载器自从JDK1.2开始便引入了一条机制叫做父类委托机制.一个类需要被加载的时候,JVM先会调用他的父类加载器进行加载,父类调用父类的父类,一直到顶级类加载 ...
- tomcat 7 中的类加载器学习
tomcat 7自带很多junit测试用例,可以帮助我们窥探源码的秘密.以下使用来测试类加载器的一个测试用例.类加载器也是对象,他们用来将类从类从.class文件加载到虚拟机,这些已经讲了很多,深入j ...
- java基础之—类加载器
要了解类加载器先要了解类的加载 一.类的加载(类的加载概述) 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 1.加载 就是指将clas ...
- Java类加载器学习笔记
今后一段时间会全面读一下<深入理解Java虚拟机> 在这里先记一下在网上看到的几篇介绍 类加载器 的文章,等读到虚拟机类加载机制再详细介绍. 超详细Java中的ClassLoader详解 ...
- Java基础加强-类加载器
/*类加载器*/ 把.class文件从硬盘上加载出来,将类的字节码(二进制)加载到内存中 /*类加载器及其委托机制*/ Java虚拟机中可以安装多个类加载器(可以自己编写),系统默认三个主要类加载器, ...
- JAVA基础_类加载器
什么是类加载器 类加载器是Java语言在1.0版本就引入的.最初是为了满足JavaApplet需要.现在类加载器在Web容器和OSGI中得到了广泛的应用,一般来说,Java应用的开发人员不需要直接同类 ...
- java 基础之--类加载器的过程
先来段代码,大家瞧瞧运行pritln的结果是什么?(认真想一想哦
随机推荐
- 翻转二叉树(深搜-先序遍历-交换Node)
题目:翻转二叉树,例如 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 已知二叉树的节点定义如下: class TreeNode { in ...
- shell执行数学运算
整数: expr let $(()) $[] 浮点数: bc 1.使用expr ♦参与运算的成员和运算符之间必须有一个空格: ♦对于那些容易被shell错解的,在它们传入expr命令之前,需要使用sh ...
- 使用echarts去对数据进行图形分析
首先导入js包:echarts.min.js <script type="text/javascript" src="js/echarts.min.js" ...
- 数据库Oracle和MySQL 的不同
实例区别: MySQL是轻量型数据库,开源免费.Oracle收费,这个不是重点,,重点是它贵. MySQL一个实例可以操作多个库,而Oracle一个实例只能对应一个库. MySQL安装只有300多兆, ...
- LightOJ1199 Partition Game
Alice and Bob are playing a strange game. The rules of the game are: Initially there are n piles. A ...
- 2017 CCPC秦皇岛 H题 Prime set
Given an array of integers , we say a set is a prime set of the given array, if and is prime. Ba ...
- 如何打造个人km知识管理系统
经常有朋友会遇到这样一种情况,在网络中看到一篇很好的文章,但后来因为关键字想不起来,结果怎么都搜索不到.还有些朋友虽然平时也会做一些记录,把有用的资料进行保存,但他们往往将保存的资料分散在不同的地方, ...
- 海思HI3518EV200+AR0130开发板DIY——前篇
海思HI3518EV200+AR0130开发板DIY 今天开始要围绕这个项目学习了(还是得从C开始学 ) 缘起(这段主要水废话)相关开发资料 →_→ 原理图设计 原理图整体框架 一.电源部分 HI35 ...
- Kubernetes基本概念和术语之《Master和Node》
Kubernetes中的大部分概念如Node.Pod.Replication Controller.Service等都可以看作一种“资源对象”,几乎所有的资源对象都可以通过Kubernetes提供的k ...
- JVM系列二(垃圾收集算法).
一.标记-清除算法(Mark-Sweep) 这种算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. Mar ...