热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

类加载器ClassLoader(一)动态加载

类,加载,器,classload

前段时间碰了下插件化,然后就简单的了解下classloader。虽然框架是能用,但是还是打算使用classloader来实现动态加载。

功能:主要开发个插件apk,里面有打印信息,然后宿主导入apk再用classloader加载出相应的类,并且调用里面的方法。

一. java的ClassLoader

1.classloader类型

先了解下java的ClassLoader,因为android的ClassLoader会有些不同。
java默认提供三种ClassLoader
(1)Bootstrp ClassLoader
(2)ExtClassLoader
(3)AppClassLoader
先记住有这三种就行,至于有什么用,就先不讲了,因为我们用到的是android的ClassLoader。还有注意的是Bootstrp ClassLoader是底层用C++写的,它们的关系是AppClassLoader继承ExtClassLoader,ExtClassLoader继承Bootstrp ClassLoader。

2.classloader工作流程

java的classloader有个双亲委派模式,网上有很多,看别人的图就能比较好懂,我这边就不盗图了。简单来说就是当需要加载一个类的时候,先去看AppClassLoader有没有加载过,没有再看ExtClassLoader有没有加载过,没有再看Bootstrp ClassLoader有没有加载过,没有再从Bootstrp ClassLoader中找是不是他那边的类,不是再向下交给ExtClassLoader处理。
双亲委派这个要记住。然后双亲委派的作用主要是能让类不重复加载和保证安全(比如你无法自定义系统类)。

二. android的ClassLoader

大概了解java的ClassLoader之后我们也来简单了解下Android的ClassLoader。

1.classloader类型

android的classloader就比较多了,没用到的后面再讲,这里我们要做动态加载,主要也是用到3个classloader
(1)ClassLoader 这是顶层的classloader类
(2)BaseDexClassLoader 这个类主要做类加载的操作
(3)PathClassLoader 这个是BaseDexClassLoader 的子类
(4)DexClassLoader 这个是BaseDexClassLoader 的子类
然后这样,BaseDexClassLoader 是做具体的操作,我打算放到后面的篇章再详细说,所以要做动态加载主要看PathClassLoader和DexClassLoader两个类。
说得简单一点,这两个类的最好区分就在构造方法。
(1)先看DexClassLoader的构造方法

public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) { super(dexPath, new File(optimizedDirectory), librarySearchPath, parent); } 

dexPath是Dex的路径,optimizedDirectory指的是优化之后的目录,有个说法是装生成的odex文件。librarySearchPath指要使用的C/C++代码,parent指父加载器。
(2)再看PathClassLoader的构造方法

public class PathClassLoader extends BaseDexClassLoader { public PathClassLoader(String dexPath, ClassLoader parent) { super(dexPath, null, null, parent); } public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) { super(dexPath, null, librarySearchPath, parent); } } 

看得出PathClassLoader只有三个构造方法,对比DexClassLoader,少了optimizedDirectory。
所以说dalvik虚拟机上PathClassLoader只能加载已安装apk的dex。而我们要实现动态加载,所以使用的类加载器是DexClassLoader

2.classloader工作流程

和java一样,也是使用双亲委派

三. 写个动态加载的Demo

我们先搞个简单的,不含任何资源,就仅仅调用Java代码,确认是否能够跑一遍流程。

1.开发插件
public class TestLog { public void say(String str){ Log.v("mmp","插件打印:"+str); } } 

我就加了这个一个类,然后打包成apk

2.宿主动态加载
 private void loadPlugin(){ try { String pluginPath = getExternalFilesDir("plugin").getPath() + "/TestPlugin.apk" ; String targetPath = getExternalFilesDir("target").getPath(); DexClassLoader dexClassLoader = new DexClassLoader(pluginPath,targetPath,null,getClassLoader()); Class cls = dexClassLoader.loadClass("com.example.kylin.testapp.TestLog"); cls.getDeclaredMethod("say",String.class).invoke(cls.newInstance(),"AAAAAAAAAAAAA"); } catch (Exception e) { e.printStackTrace(); Log.v("mmp","错误:"+e.toString()); } } 

简单就这样写,我们把插件打出的apk命名为TestPlugin.apk,然后放到plugin文件夹下,调用DexClassLoader 去获取到Class,再用反射调用Class的say方法,最后看结果


img_08e721286f94fb6466ba71d3a1a55389.png

确实是有打印的,这样我们就相当于能正常跑完一个动态加载类的流程。但是这个地方还是有些问题,运行之后我看了下target文件夹是没东西的,而odex文件是在plugin文件夹下生成了一个oat文件夹里面,这就比较奇怪,我先看看什么原因再补上。


推荐阅读
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 本文介绍了一种在 Android 开发中动态修改 strings.xml 文件中字符串值的有效方法。通过使用占位符,开发者可以在运行时根据需要填充具体的值,从而提高应用的灵活性和可维护性。 ... [详细]
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • java datarow_DataSet  DataTable DataRow 深入浅出
    本篇文章适合有一定的基础的人去查看,最好学习过一定net编程基础在来查看此文章。1.概念DataSet是ADO.NET的中心概念。可以把DataSet当成内存中的数据 ... [详细]
  • 本文探讨了在使用 MyBatis 进行批量数据处理时遇到的参数绑定异常问题,并提供了详细的解决方案。 ... [详细]
  • 使用 ModelAttribute 实现页面数据自动填充
    本文介绍了如何利用 Spring MVC 中的 ModelAttribute 注解,在页面跳转后自动填充表单数据。主要探讨了两种实现方法及其背后的原理。 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • 我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ... [详细]
  • 本文详细探讨了 Android Service 组件中 onStartCommand 方法的四种不同返回值及其应用场景。Service 可以在后台执行长时间的操作,无需提供用户界面,支持通过启动和绑定两种方式创建。 ... [详细]
  • 本文详细探讨了在Windows 98环境下安装Apache 1.3.9、JServ、GNUJSP 1.0、JDK 1.2.2及JSDK 2.0后遇到的中文显示问题,并提供了多种有效的解决方案。 ... [详细]
  • Java中List的forEach方法与字符串拼接的兼容性问题
    本文深入探讨了在Java中使用List的forEach方法时遇到的字符串拼接问题,提供了有效的解决方案及背后的原理分析,旨在帮助开发者更好地理解和解决此类问题。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • Docker基础入门与环境配置指南
    本文介绍了Docker——一款用Go语言编写的开源应用程序容器引擎。通过Docker,用户能够将应用及其依赖打包进容器内,实现高效、轻量级的虚拟化。容器之间采用沙箱机制,确保彼此隔离且资源消耗低。 ... [详细]
author-avatar
古月礻羊米兰_318
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有