【Dexclassloader】学习
在 Java 里面,我们可以把一些类放到 .jar 文件里面,然后用 ClassLoader 动态加载。例如:
URLClassLoader ucl = URLClassLoader.newInstance(new URL[]
{new URL("file:/sdcard/files/test.jar")});
Class clazz = ucl.loadClass("com.test.TestClass");
Android 里面虽然也提供了 URLClassLoader 的实现,但是并不能用。要动态加载其它类,可以用的 Class Loader 有BaseClassloader的两个子类:
DexClassLoader:DexClassLoader 可以加载 apk, jar 或者 dex 文件
File jarFile = new File("/sdcard/test.dex");
if ( jarFile.exists() ) {
DexClassLoader cl = new DexClassLoader(jarFile.toString(), "/sdcard/test", null, ClassLoader.getSystemClassLoader());
Class<?> c = cl.loadClass("com.qihoo360.test.Test");
...
}
但是 DexClassLoader 要求指定一个可写的目录,即 DexClassLoader 构造函数的第二个参数,在上例中是 /sdcard/test
这个参数的含义是:directory where optimized DEX files should be written
因为 Dalvik 在加载 dex 文件时,会动态进行优化,DexClassLoader 要求指定优化后 dex 文件存放的位置。
DexClassLoader dexClassLoader = new DexClassLoader(
"/mnt/sdcard/tangsilian.jar", "/mnt/sdcard/tangsilian", null,
this.getClass().getClassLoader());
/**
* java反射調用jar包裡面的方法
*/
try {
// 拿到jar包裡的class對象
Class<?> class1 = dexClassLoader
.loadClass("com.klsd.tools.IMSIParas");
// 实例化这个对象
Object object = class1.newInstance();
// 参数类型
Class paramtype = dexClassLoader.loadClass("java.lang.String");
Class[] paramtypeclass = new Class[] { paramtype };
// 参数配置
String[] param = new String[1];
param[0] = imsi;
Toast.makeText(getApplicationContext(), "dao", 0).show();
// 找到要動態加載的方法并传入参数
Method method = class1.getMethod("getMobileByIMSI", paramtypeclass);
String str = (String) method.invoke(object, param);
text.setText(str);
PathClassLoader:它只能加载已经安装到 Android 系统中的 apk 文件,也就是 /data/app 目录下的 apk 文件。
[java] view plain copy print?PathClassLoader cl = new PathClassLoader(jarFile.toString(), "/data/app/", ClassLoader.getSystemClassLoader());
dexclassloader
不是普通类怎么办?
系统组件如何接收回调?
如何加载资源?
PackageInfo处理?
Resources的处理?
Assets的处理?
dex分包
原因一个dex里面方法数目不能超过65536个
或者一个dex文件不能超过65k
所以需要分包/或者动态加载
xposed学习
原理
- 替换系统的app_process(当然,这个操作需要Root权限)
app_process是什么看init.rc?
service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
app_process是andriod app的启动程序(具体形式是zygote fork()调用一个 app_process作为Android app的载体)
- 将xposed的api文件,XposedBridge.jar文件放置到私有目录中并且buildpath
- 注意配置模块meta-data
- 设置一个main类来实现xposed的接口
然后新建一个xposed_init文件,声明主入口类
然后xposed的jar包不能放在libs目录下面。放在自己新建一个lib目录然后bulidpath
- findAndHookMethod找到要hook的包名函数名等beforehook和afterhook改变原来代码的执行逻辑
在我github上能找到源码:
https://github.com/tangsilian/SecurityPage
- 但是每次重启太麻烦,而且还需要root权限
- 进阶的可以用缩水版的dexposed或者Andfix或者360的DroidPlugin
我理解的:双开其实就把原来的apk文件再执行一遍:应用程序本身是运行在虚拟机上的,再虚拟一次。
一般apk安装是移动到
/data/app目录下,
再建一个/data/data/packagename的目录
还有/davlik/cache存放优化的odex
双开就是不安装,但同时完成上面的过程
欺骗虚拟机,并虚拟出对应运行环境。在 /sdard/parallel/ 下有对应的目录虚拟内置存储的目录。但是有时候双开打开文件存储的应用会失败。是因为存储空间是虚拟出来模拟系统存储的。比如小米的双开应用两个存储网络图片的位置就不同。
那么应用分身又与双开是什么关系呢?
分身不是创建了图标吗?有没有app2?
遇到的问题:
解决genymotion 无法使用adb的问题
- Genymotion设置->Setting->ADB->use custom Android SDK tools换成自己的sdk即可解决
然后:Android Xposed框架出现java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation问题
- 然后xposed的jar包不能放在libs目录下面。放在自己新建一个lib目录然后bulidpath