android类,android类加载机制

Android开发的分类有哪些?

1、Android客户端应用程序

河间网站制作公司哪家好,找成都创新互联!从网页设计、网站建设、微信开发、APP开发、响应式网站等网站项目制作,到程序开发,运营维护。成都创新互联从2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联

如新浪微博、网银客户端、凡客、淘宝客户端,快盘客户端。Android在这里的应用还是界面层的东西为主。核心还在WEB。客户端界面很重要,用户体验度很重要。从应用需求上来讲,几乎大一点的网站,都需要有手机客户端程序。

2、Android通用类程序

如基于LBS(基于位置的服务)的应用(这类一般会嵌入到客户端应用程序中),流媒体播放应用。由于移动设备的方便便捷、3G、4G网络的发展,这类应用有不错的前景。

3、Android游戏开发

需要掌握的游戏引擎LGame,游戏框架等。手机上的游戏会是一大块内容,有前途。

4、Android底层开发

需要掌握C、Linux等较底层的东西,发展方向应该是驱动、协议开发,嵌入式开发。

Android-类加载

双亲委托机制

类在进行类加载的时候,把加载任务托管给父类加载器,如能加载成功,则返回,否则依次向子类加载器递归尝试类加载。

意义:

①避免类的重复加载,父类加载已加载该类时,子ClassLoader就没有必要加载一次了。

②安全性,防止核心API被随意篡改。

ClassLoader

ClassLoader本身是一个抽象方法。它的主要实现类有BootClassLoader、PathClassLoader、DexClassLoader.

BootClassLoader:用于加载Android Framwork层(SDK)的class文件

PathClassLoader:用于Android应用程序加载器,可以加载指定的dex和jar、zip、apk中的classes.dex(系统使用)

DexClassLoader:用于加载指定的dex和jar、zip、apk中的classes.dex。(供开发者使用)

拓展:

在API26之前。

optimizedDirectory 参数就是dexopt的产出目录(odex)。那 PathClassLoader 创建时,这个目录为null,就

意味着不进行dexopt?并不是, optimizedDirectory 为null时的默认路径为:/data/dalvik-cache。

在API26之后DexClassLoader也取消了optimizedDirectory

热修复相关

LoadClass:

findClass:PathClassLoader和DexClassLoader的父类BaseDexClassLoader中实现findClass。

BaseDexClassLoader中

PathClassLoader加载过后,pathlist 中存在一个Element数组,Element类中存在一个dexFile成员表示dex文件,即:APK中有X个dex,则Element数组就有X个元素。

总结:

可能看到这里我们比较乱了,理一下。一个类的加载经历了哪些。我们以PathClassLoader为例。

①加载一个类的时候,首先通过Class缓存寻找是否已经加载过该类。参考抽象类的loadClass方法。

②若在缓存中未找到该类,则交由父加载器加载该类。参考抽象类的loadClass方法。

③调用父加载器PathClassLoader的父类BaseDexClassLoader实现的findClass方法加载该类。

④PathClassLoader在初始化的时候调用父构造方法实例化DexPathList属性,DexPathList属性初始化时构造方法内通过makePathElements(或makeDexElements 不同API可能不同)加载APK内的dex文件生成Element数组。

⑤BaseDexClassLoader实现的findClass方法中顺序循环已存在的Element数组,通过Element中的DexFile加载类。。

⑥未找到,抛出类未找到异常。

热修复(multide 形式(thinker、qfix))

热修复的原理。我们只需在应用启动的时候,一般是在application方法中(因为class加载首先从缓存中加载),在应用启动后,经过PathClassLoader加载过后所有的类都在 pathList的Element 数组,把生成的Elment数组插入到PathList的Element数组的最前方。在加载类的时候就只会加载到我们需要更新的类了,因为是顺序寻找,找到就返回。(先从我们补丁的dex文件生成的element寻找,找不到再从APK的dex生成的element种寻找)。

热修复基本思路总结:

①获取到当前引用的PathClassLoader

②反射获取其中DexPathList属性:DexPathList pathList.

③获取到补丁包path.dex文件的Element[]数组 pElements。参考PathClassLoader怎么把dex文件转换为Element数组的。于是我们反射执行DexPathList 中的makePathElements方法(视API而定)传入dex路径得到补丁包的element数组。

④获取pathList的dexElements数组。

⑤把补丁包的pElements数组合并到pathList的dexElements数组的前方,即newElements=pElements+dexElements

⑥反射赋值把newElements替换掉pathList的dexElements

热修复没这么简单,还需考虑混淆,API版本不同导致的使用makePathElements方法或makeDexElements方法等因素。

热修复(InstantRun 形式(Robust))待了解。

【Android】Android中的类加载

前文: 【Java】ClassLoader与双亲委派机制

Android中的类加载器有三种, DexClassLoader 、 PathClassLoader 、 BootClassLoader 。

其中 BootClassLoader 是系统启动时预加载常用类的,一般使用不到。 DexClassLoader 、 PathClassLoader 都是继承自 BaseDexClassLoader 。

但 DexClassLoader 和 PathClassLoader 并没有重写 BaseDexClassLoader 中的任何方法,所以源码只需要看 BaseDexClassLoader 即可。

由于Android SDK并没有包含 BaseDexClassLoader ,所以需要到源码查询网站查询源码,如下:

复制这个java文件到对应源码文件夹下就可以在Android Studio中查看了。

通过调试可以看到,Android中普通类的加载器其实是 PathClassLoader 。追踪 PathClassLoader.findClass 方法,即可获取Android的类加载过程:

PathClassLoader.findClass -- 继承自 -- BaseDexClassLoader.findClass()

- BaseDexClassLoader.pathList.findClass()

- DexPathList.dexElements.foreach { element.findClass() }

- Element.findClass()

- Element.dexFile.loadClassBinaryName()

- DexFile.defineClass()

即类加载过程通过 BaseDexClassLoader.findClass 、 DexPathList.findClass 、 Element.findClass 、 DexFile.loadClassBinaryName ,最终会落到 DexFile.defineClass 方法中,然后就交给native层了。

其中需要注意的是,在 BaseDexClassLoader.findClass 的开头有这么一段:

这段是在Android 10新加入的,据称是为了实现 shared library 功能的,在之前的版本中没有这一段。

在上一节中知道了,类加载的流程如下:

BaseDexClassLoader.findClass() -

BaseDexClassLoader.pathList.findClass() -

DexPathList.dexElements.foreach { element.findClass() } -

Element.findClass() - ...

看 DexPathList.findClass 方法:

可以发现, DexPathList 加载类的方法是遍历 dexElements 数组依次加载,知道获取到值为止。所以可以通过修改这个数组,把新的dex文件放在数组的前面,使其加载修改后的类,从而实现热修复。

根据以上原理,写下这个工具类,有效性待验证:


分享文章:android类,android类加载机制
网页地址:http://ybzwz.com/article/dsgigsg.html