利用DexClassLoader解决方法越界
来源:互联网 发布:4k电视盒子 知乎 编辑:程序博客网 时间:2024/05/22 16:10
背景:
Android工程方法数超过65535,则会提示编译错误(jar包太多)。为了减少jar包,可将一部分jar包转成dex文件(dex:andorid系统对jar的一些优化处理),dex文件在运行期间通过DexClassLoader加载至内存,从而避免方法数越界。
原理:
1.使用ClassLoader的好处:
扩充jar文件;
修改Framework中的已有类文件;
2.为什么使用DexClassLoader:
在Android中,ClassLoader是抽象类,一般使用DexClassLoader或者PathClassLoader加载,他们的区别是
DexClassLoader可以加载jar/apk/dex,可以从SD卡中加载未安装的apk
PathClassLoader只能加载系统中已经安装过的apk
源码,
public class DexClassLoader extends BaseDexClassLoader { public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent) { super(dexPath, new File(optimizedDirectory), libraryPath, parent); } }
public class PathClassLoader extends BaseDexClassLoader { public PathClassLoader(String dexPath, ClassLoader parent) { super(dexPath, null, null, parent); } public PathClassLoader(String dexPath, String libraryPath, ClassLoader parent) { super(dexPath, null, libraryPath, parent); } }
- dexPath: 指目标类所在的jar/apk文件路径, 多个路径使用
File.pathSeparator分隔, Android里面默认为 “:” - optimizedDirectory:
解压出的dex文件的存放路径,以免被注入攻击,不可存放在外置存储。(DexClassLoader 的optimizedDirectory不能为空) - libraryPath :目标类中的C/C++库存放路径。
- parent: 父类装载器
3.生成所需dex包
cmd至sdk解压目录…\AndroidSDK\build-tools\android-4.4W,
将jar文件转换成dex二进制jar文件:dx –dex –output=classes.dex libs(libs是要转换的jar文件总目录)
4.通过DexClassLoader加载生成的dex文件
- 将classes.dex放在工程的asserts资源目录下(或者手机内部存储)
- 生成dex文件输出流
在自定义Application中,重写attachBaseContext,插入
String fileName = "classes.dex";String internalPath = context.getExternalCacheDir() + File.separator + "classes.dex";File desFile = new File(internalPath);InputStream in = null;OutputStream out = null; try { in = context.getApplicationContext().getAssets().open(fileName); out = new FileOutputStream(desFile.getAbsolutePath()); byte[] bytes = new byte[1024]; int i; while ((i = in.read(bytes)) != -1) out.write(bytes, 0 , i); } catch (IOException e) { e.printStackTrace(); }finally { try { if (in != null) in.close(); if (out != null) out.close(); } catch (IOException e) { e.printStackTrace(); } }
- 设置输出流的类加载器
try { Field field = ClassLoader.class.getDeclaredField("parent"); field.setAccessible(true); ClassLoader classLoader = context.getApplication().getClassLoader(); //设置dexclassloader解析的文件目录 File dexdst = new File(desFile, "dst"); dexdst.mkdir(); DexClassLoader dexClassLoader = new DexClassLoader(desFile.getAbsolutePath(), dexdst.getAbsolutePath(), context.getApplication().getApplicationInfo().nativeLibraryDir, classLoader.getParent()); field.set(classLoader, dexClassLoader); } catch (Exception e) { throw new RuntimeException(e); }
阅读全文
0 0
- 利用DexClassLoader解决方法越界
- DexClassLoader
- Multidex解决方法数越界
- 解决方法数越界
- multidex解决方法数越界
- 利用DexClassLoader动态加载dex文件
- 使用Multidex解决方法数越界
- Android系统解决方法数越界
- C++内存越界问题及解决方法
- C++内存越界问题及解决方法
- 利用保护页检测内存访问越界
- Android利用AChartEngine作图时报索引越界
- 利用 _RTC_CheckStackVars(...) 和 windbg 发现访问越界
- 利用 _RTC_CheckStackVars(...) 和 windbg 发现访问越界
- 越界
- DexClassLoader简介
- DexClassLoader简介
- DexClassLoader 插件
- SVN目录/文件被删除后如何恢复
- 欢迎使用CSDN-markdown编辑器
- SQLSERVER 查询当前数据的上一条、下一条
- mysql查询 根据年月日的查询
- 玲珑1117RE:从零开始的异世界生活(线段树+思路)
- 利用DexClassLoader解决方法越界
- 栈区和堆区内存分配
- Zookeeper报KeeperErrorCode = MarshallingError 错误的说明
- python 操作MQ
- Node.js实战:Express实现简单后台登录系统
- 【在线支付】在线支付代码详解
- window cmd编码改变
- 指令 AngularJs
- JSTL fn 标签库