【Dexclassloader】学习

来源:互联网 发布:青藏铁路知乎 编辑:程序博客网 时间:2024/05/21 23:05

在 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
0 0
原创粉丝点击