DexClassLoader的使用

版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/47146613

在Java环境中,有个概念叫做”类装载器(Class Loader)”,其作用是动态加载Class文件.标准的Java SDK中有一个ClassLoader类,借助他可以装载想要的Class文件,每个ClassLoader对象在初始化的时候必须指定Class文件的路径.

但我们在使用java的时候,基本上没有使用过ClassLoader,仅仅使用import就可以加载类文件了,简单的讲,import中所引用的类文件有两个特点:

1:必须存在于本地,当程序运行需要该类的时候,内部类装载器会自动装载该类,这对程序员来说是透明的,即程序员感知不到该过程
2:编译时必须在现场,否则编译过程会因找不到引用文件而不能正常编译.

但在有些情况下,所需要的类却不能满足以上两个条件.比如当该类是从远程下载并在本地执行的时候,典型的例子就是通过浏览器中的AppletLet执行的java程序,这些要执行的程序是在服务器端.另一种情况是,要引用的Class文件不方便在编译的时候直接参与,而只能在运行时动态调用.例如,在Android Framework中,所包含的Class文件是一些通用的类文件,但对于一些设备商而言,他们需要扩充Framework,扩充的具体工作包括两点:

1:需要增加一些额外的类文件,这些类文件提供厂商自定义的功能,这些文件一般以独立的jar包存在

2:需要修改Framework中的已有的类文件,比如WindowManagerService类,在该类中添加使用自定义jar包中的代码.使用自定义jar常用的方法是使用import关键字包含自定义的类,但为了保持和原生Framework的兼容性,对原声Framework最少化修改,可以使类装载器动态装载自定义jar包.

这就是使用ClassLoader的原因.

在一般情况下,应用程序不需要创建一个全新的ClassLoader对象,而是使用当前环境已经存在的ClassLoader.因为java的Runtime环境在初始化时,其内部会创建一个ClassLoader对象用于加载Runtime所需的各种java类.

每个ClassLoader必须有一个父ClasLoader,在装载Class文件的时候,子ClassLoader会先请求其父ClassLoader加载该Class文件,只有当其父ClassLoader找不到该Class的时候,子ClassLoader才会急促装载该类,这是一种安全机制.

对于Android的应用程序,本质上虽然也是用Java开发,并且使用标准的Java编译器编译出Class文件,但最终的APK文件中包含的确实dex类型的文件.dex文件是将所需的所有Class文件重新打包,打包的规则不是简单的压缩,而是完全对Class文件内部的各种函数表,变量表等进行优化,并产生一个新的文件,这就是dex文件.由于dex文件是一种经过优化的Class文件,因此要加载这样特殊的Class文件就需要特殊的类装载器,这就是DexClassLoader.Android SDK中提供了DexClassLoader类就是处于这个目的.

下面我们就来看一下DexClassLoader的调用.

首先我们新建一个Android Project,命名为Plugin.我们的包名设置为:
com.chen.plugin

在我们的包com.chen.plugin中创建一个activity,这个随便创建,我们用不到这个,该activity的用处仅仅就是用于启动android程序的.

在包com.chen.plugin中创建一个新的class,命名为PluginClass.

在类PluginClass中我们添加一个函数,名称为function1(int a,int b).

看一下我们的代码:

package com.chen.plugin;import android.util.Log;public class PluginClass {public PluginClass(){Log.e("Plugin","PluginClass client initialized");}public int function1(int a,int b){return a+b;}
}

然后运行我们这个项目,在手机中安装.

第二步,我们创建一个新的Android Project,命名为Host.同样创建一个新的Activity.

在MainActivity中添加一个方法,useDexClassLoader(),下面看一下这个方法的具体实现.

public void useDexClassLoader(){Intent intent = new Intent(Intent.ACTION_MAIN,null);intent.addCategory(Intent.CATEGORY_LAUNCHER);              PackageManager pm = getPackageManager();final List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);ResolveInfo rinfo = null;if(plugins != null){for(int i = 0;i < plugins.size();i++){ResolveInfo r = plugins.get(i);ActivityInfo ainfo = r.activityInfo;String div = System.getProperty("path.seperator");String packageName = ainfo.packageName;if(packageName.equals("com.chen.plugin")){rinfo = plugins.get(i);}}}ActivityInfo ainfo = rinfo.activityInfo;String div = System.getProperty("path.seperator");String packageName = ainfo.packageName;String dexPath = ainfo.applicationInfo.sourceDir;String dexOutputDir = getApplicationInfo().dataDir;String libPath = ainfo.applicationInfo.nativeLibraryDir;DexClassLoader cl = new DexClassLoader(dexPath, dexOutputDir, libPath, this.getClass().getClassLoader());try{Class<?> clazz = cl.loadClass(packageName+".PluginClass");Object obj = clazz.newInstance();Class[] params = new Class[2];params[0] = Integer.TYPE;params[1] = Integer.TYPE;Method action = clazz.getMethod("function1", params);Integer ret = (Integer)action.invoke(obj, 12,34);Log.e("Host","return value is"+ret);}catch(Exception e){Log.e("errpr",e.getMessage());}}

在我们的MainActivity的OnCreate()方法中调用该方法,然后在手机中运行Host,就可以看到我们的调试信息.

我们先来看一下结果:

很明显,Plugin中的函数在Host中被调用了.

下面我们看一下DexClassLoader构造函数的参数的意义:

  • 1:dexPath,指目标类所在的APK或jar文件的路径.类装载器将从该路径中寻找指定的目标类,该类必须是APK或jar的全路径.如果要包含多个路径,路径之间必须使用特定的分割符分隔,特定的分割符可以使用System.getProperty(“path.separtor”)获得.
  • 2:dexOutputDir,由于dex文件被包含在APK或者Jar文件中,因此在装载目标类之前需要先从APK或Jar文件中解压出dex文件,该参数就是制定解压出的dex 文件存放的路径.在Android系统中,一个应用程序一般对应一个Linux用户id,应用程序仅对属于自己的数据目录路径有写的权限,因此,该参数可以使用该程序的数据路径.
  • 3:libPath,指目标类中所使用的C/C++库存放的路径
  • 4:最后一个参数是指该装载器的父装载器,一般为当前执行类的装载器

创建了DexClassLoader对象之后,就可以调用loadClass()来装载指定的类了.该函数返回的是一个Class对象,注意区分Class对象和目标类PluginClass对象,Class对象是ClassLoader所能识别的类,而PluginClass是程序执行后所能识别的类,此时仅仅装载了PluginClasss的程序代码,但是还没有创建 PluginClass对象,因此接下来调用Class对象的newInstance()方法,该方法内部会调用PluginClass的构造函数,并返回i一个真正的PluginClass对象.

虽然生成了PluginClass对象,但是Host本地并没有其函数,所以只能使用反射机制来调用PluginClass的方法.

关于反射机制,后面文章中会有更加详细的使用方式.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这才是老公的正确用法,不吃就往死里打......

1 倒是好办法就是有点儿费爸爸▼2 一只被主人遗弃的小熊的奇幻旅程▼3 小子&#xff0c;你单身的命运gu7在你把美女老师撂倒那一刻就注定了...▼4 张萌姐姐自我肯定式唱歌▼5 &#xff1f;&#xff1f;&#xff1f;有被冒犯到▼6 听说昨天有个少年28岁就退休了▼7 哪个男…

C# WPF MVVM模式下在主窗体显示子窗体并获取结果

01—前言在winform中打开一个新的子窗体很简单&#xff0c;直接实例化窗体并show一下就可以&#xff1a;Form2 f2 new Form2();f2.Show();或者Form2 f2 new Form2();f2.ShowDialog();但是&#xff0c;在wpf的mvvm模式下&#xff0c;这种方法是行不通的&#xff0c;因为逻辑是…

Exchange 2010发现拓扑失败

今天跟大家继续分享一个我在项目中遇到的问题哈&#xff0c;希望对大家今后的项目排错有帮助。问题背景&#xff1a;企业主域控从 Window Server 2003升级为Windows Server 2012 R2具体实施方法可以参考我之前的文章(http://horse87.blog.51cto.com/2633686/1613268)在顺利升级…

html引用单文件组件,vue之单文件组件 纯网页方式引入

上一节的vue组件开发是把组件内容统一放到了一个js文件里面里面写上模板字符串(引用组件) 这种方式还需要拼接转义 写法非常丑陋vue贴心的帮我们封装了单文件组件 可以不用再模板里面拼接字符串下面看下写法由于我们目前没有使用webpack和vue-cli等构建工具(为了快速学习vue的语…

足不出户,游遍七大洲,不可错过的14部地理纪录片!

见识是超越时间与空间的力量&#xff0c;使人身未行&#xff0c;而心已至之。今天的资源分享就从七大洲为切入点&#xff0c;为各位献上最值得观看的14部地理纪录片&#xff0c;与各位一起探索各大洲的独一无二的自然与人文景观&#xff0c;从这些丰富的影像中&#xff0c;不仅…

在Cocos2d中实现能够惯性拖动的选择界面

苹果的应用讲究用户体验 有的时候仔细想想 的确&#xff0c;很多细节决定了用户体验 比如说惯性拖动 可以说之前没有任何一家厂商能把触摸惯性拖动做的像苹果的UI那么流畅 Cocos2D中实现能够惯性拖动的选择界面 完成的效果&#xff1a; 制作一个简单的图层&#xff0c;通过传入…

SignalR在React/Go技术栈的实践

哼哧哼哧半年&#xff0c;优化改进了一个运维开发web平台。本文记录SignalR在react/golang 技术栈的生产小实践。01背景有个前后端分离的运维开发web平台&#xff0c; 后端会间隔5分钟同步一次数据&#xff0c;现在需要将最新一次同步的时间推送到web前端。说到[web服务端推送]…

16张扎心漫画,戳中女生私密日常,每一幕都很真实

全世界只有3.14 % 的人关注了爆炸吧知识比利时的插画师Planet Prudence&#xff0c;画了很多女生的真实日常&#xff0c;每一幕都很戳心&#xff0c;一起来看看吧。别人的痘痘一长就是一个&#xff0c;我一长就是一片。买买买的时候爽得要命&#xff0c;要穿的时候总觉得自己没…

Magicodes.IE 2.5.6.2发布

2.5.6.22021.10.13支持自定义列字体颜色&#xff0c;具体见PR#342&#xff0c;感谢xiangxiren修复日期格式化的问题&#xff0c;具体见PR#344&#xff0c;感谢ccccccmd2.5.6.12021.10.06修复 #337&#xff0c;bool?类型导出的映射问题2.5.6.02021.10.05合并Magicodes.EPPlus到…

一个让我很不爽的外包项目——奔驰Smart2015新官网

七月份的下半个月&#xff0c;有幸做了奔驰 Smart 2015年新官网&#xff0c;包括手机端和PC端的宣传页&#xff0c;地址&#xff1a; PC端手机端这里&#xff0c;为了证明这个是一个事实&#xff0c;我还特意的留存了两张截图&#xff1a; 这里只想说明这么几个问题&#xff1a…

为什么饮料瓶大都是圆的,牛奶盒却是方的?原因你想不到

全世界只有3.14 % 的人关注了爆炸吧知识每日看着电视玩着手机再喝着饮料那是相当美好但是喝了这么久的饮料你有没有想过一个问题为什么饮料瓶一般都是圆的&#xff1f;而牛奶盒却是方的&#xff1f;图片来源网络有的人可能会说饮料瓶要拿在手上当然是圆的舒服啊拿着一个方形的饮…

IIS相关问题及解决方案

1、问题&#xff1a;HTTP 错误 500.19 - Internal Server Error无法访问请求的页面,因为该页的相关配 可能原因&#xff1a;在自己使用IIS发布网站之后&#xff0c;自己所使用的当前账户的密码改变了。 解决方法&#xff1a;将用户才密码改回来即可.... 2. 转载于:https://www.…

博客园html源码编辑出错,博客园小技巧

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01;在博客园写博的半年中&#xff0c;我有时会纠结于一些诸如写作格式和显示效果之类的小问题。我想任何一个热衷于在这里写博客的人都可能会遇到类似…

使用零代码平台构建应用,应该怎样转变思路?

最近两年&#xff0c;越来越多的各类零代码产品在市场上出现&#xff0c;与此同时&#xff0c;企业的数字化转型的速度也越来越快&#xff0c;零代码产品已然成为了帮助企业数字化转型的利器。技术也在不断地演进&#xff0c;其核心目的就是让开发人员能够更专注于业务逻辑&…

看了这几幅图,感觉自己物理白学了!

全世界只有3.14 % 的人关注了爆炸吧知识看完觉得自己即将成为21世纪最伟大的科学家&#xff01;据说&#xff0c;物理老师看到这几幅图&#xff0c;会说不出话来……不信&#xff0c;转给你们老师看看&#xff0c;嘿嘿嘿……来源&#xff1a;物理知识大全

在Web应用中使用localforage存储离线数据

在现代Web应用中&#xff0c;我们经常会需要在本地存储一些数据&#xff0c;一方面记住用户的一些状态&#xff0c;或个性化设置&#xff0c;尤其是可以缓存一些常用&#xff08;甚至全部&#xff09;的数据&#xff0c;实现更加强大和丰富的本地交互体验。传统上说&#xff0c…

出差一定要给孩子带特产

1 这就是热恋期管不住自己的情侣▼2 热恋期过了...▼3 这该夸你腰细呢&#xff1f;还是脸大呢&#xff1f;▼4 听起来...不是挺好的吗▼5 由于新冠病毒&#xff0c;美国GCW选手都保持着一定距离改用原力来进行比赛▼6 她们太菜了你跟她们好以后肯定疯狂掉分▼7 出差一定…

计算机用户名密码策略,设置域用户帐户密码策略

从安全和易用考虑&#xff0c;普通域用户的帐户策略必须满足一下要求&#xff1a;u 密码长度至少3位u 最长使用期限60天u 密码必须符合复杂性要求u 密码最短使用0天u 帐户锁定阀值7次u 帐户锁定时间30分钟u 复位帐户锁定计数器30分钟任务:u 使用默认域策略设置域用户帐户策略u …

优秀的硕博士们,他们的朋友圈都有什么特点?

全世界只有3.14 % 的人关注了爆炸吧知识很多同学都会有这种感觉&#xff0c;读了硕士博士后&#xff0c;兴趣会突然间发生很大变化&#xff0c;发朋友圈也会不一样了。例如&#xff0c;合格的学术研究者&#xff0c;要快速、全面的获取各种最新文献和学界动态&#xff1b;还要持…

未来教育计算机二级Excel解析,Excel操作小技巧,助你学好计算机二级office!

原标题&#xff1a;Excel操作小技巧&#xff0c;助你学好计算机二级office&#xff01;Office考试中最难的是什么&#xff1f;当然是Excel函数啊&#xff01;小编辛苦整理了excel10大懒人技巧&#xff0c;让你考试速提分&#xff01;还不赶紧收藏起来一、填充合并单元格在工作表…