DexClassLoader类的源码
package dalvik.system;public class DexClassLoader extends BaseDexClassLoader {public DexClassLoader(String dexPath, String optimizedDirectory,String librarySearchPath, ClassLoader parent) {super(dexPath, null, librarySearchPath, parent);}
}
DexClassLoader
类构造方法参数:
String dexPath
:指定了 .dex 文件的路径。String optimizedDirectory
:指定了优化后的 .dex 文件存放的目录。在 Android 系统中,为了提高应用的启动速度和运行效率,会对 .dex 文件进行优化,生成 .odex 文件。这个参数就是用来指定优化后的 .odex 文件存放的位置。String librarySearchPath
:指定了系统库文件的搜索路径。ClassLoader parent
:指定了父类加载器。
编写插件加载dex中的类,并调用其中的函数
PluginDex01
新建一个native工程PluginDex01
创建一个类
public class PluginClass {public static void testMethod(){Log.e("plugindex","testMethod is called");}
}
然后编译生成apk(Build apk),然后提取apk
这里生成了四个dex文件,查看他们的内容找到有testMethod
函数的dex文件
通过jadx反编译dex找到在class3.dex
里
把class3.dex
改名为plugin.dex
,然后通过adb把它push到/data/local/tmp
目录下
PluginDex02
新建一个工程PluginDex02,用来加载dex中的PluginClass
类并调用testMethod
函数
首先需要在AndroidManifest.xml
中添加sdcard
读取权限
编写代码加载plugin.dex并调用testMethod
函数
String dexpath = "/data/local/tmp/plugin.dex"; // dex路径DexClassLoader dexClassLoader = new DexClassLoader(dexpath,this.getApplication().getCacheDir().getAbsolutePath(),null,MainActivity.class.getClassLoader());try {Class PluginClass = dexClassLoader.loadClass("com.example.plugindex01.PluginClass"); // 加载类Log.e("PluginDex02",dexClassLoader.toString()+"---"+PluginClass.toString());Method testMethod = PluginClass.getMethod("testMethod");testMethod.invoke(null);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}
-
打印
dexClassLoader
的父类加载器
printClassLoader(dexClassLoader);
this->dalvik.system.DexClassLoader[DexPathList[[dex file "/data/local/tmp/plugin.dex"],nativeLibraryDirectories=[/system/lib64]]] parent->dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.plugindex02-GQcsk_5ktyHhY_g_qUMA-A==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.plugindex02-GQcsk_5ktyHhY_g_qUMA-A==/lib/arm64, /data/app/com.example.plugindex02-GQcsk_5ktyHhY_g_qUMA-A==/base.apk!/lib/arm64-v8a, /system/lib64]]] parent->java.lang.BootClassLoader@84d413c parent is null
dexClassLoader
的类加载器是DexClassLoader
,父类加载器是PathClassLoader
,再往上是BootClassLoader
,再往上就是空了 -
把dexClassLoader里的父类加载器修改为String类的类加载器
只需要在DexClassLoader
类的构造方法里把最后一个参数父类加载器修改为String类的类加载器即可String dexpath = "/data/local/tmp/plugin.dex"; // dex路径DexClassLoader dexClassLoader = new DexClassLoader(dexpath,this.getApplication().getCacheDir().getAbsolutePath(),null,String.class.getClassLoader());
打印结果
dexClassLoader
的父类加载器变成了BootClassLoader