类列表
每一个ClassLoader里面的类列表,类的数量都是固定的。
对上一节中的dex反编译
使用DexClassLoader类动态加载插件dex
利用jadx对dex进行反编译可以看到有哪些类
源码分析
-
BaseDexClassLoader
从BaseDexClassLoader
类加载器开始分析
在BaseDexClassLoader
类里有一个pathList
属性,它的类型是DexPathList
,分析DexPathList
类的定义
-
DexPathList
在DexPathList
类里有一个dexElements
属性,它是Element
类型,分析Element
类的定义
-
Element
Element
类是DexPathList
的内部类,它有一个属性是dexFile
,它是DexFile
类型,分析DexFile
类的定义 -
DexFile
在DexFile
里找到一个方法getClassNameList()
,获取类名,它需要一个参数cookie
cookie
参数就是DexFile
类的属性mCookie了
接下来通过反射调用getClassNameList()方法就可以得到类加载器可以加载的类了。
代码
public static void getClassListInClassLoader(ClassLoader classLoader) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {// 获取BaseDexClassLoader类Class BaseDexClassLoaderClass=Class.forName("dalvik.system.BaseDexClassLoader");// 获取BaseDexClassLoader类中的pathList字段Field pathListField = BaseDexClassLoaderClass.getDeclaredField("pathList");// 设置权限pathListField.setAccessible(true);// 从传进去的参数classLoader加载器对象中获取pathList对象Object pathListobj = pathListField.get(classLoader);// 获取DexElemtnt类Class DexElemtntClass = Class.forName("dalvik.system.DexPathList");// 获取DexElemtnt类中的dexElements字段Field dexElements = DexElemtntClass.getDeclaredField("dexElements");// 设置权限dexElements.setAccessible(true);// pathList对象中获取dexElements对象Object[] dexElementsArratobj = (Object[]) dexElements.get(pathListobj);// 获取Element内部类Class ElementClass = Class.forName("dalvik.system.DexPathList$Element");// 从Element内部类中获取字段dexFileField dexFileField = ElementClass.getDeclaredField("dexFile");设置权限dexFileField.setAccessible(true); // 取消权限检查// 获取DexFile类Class DexFileClass = Class.forName("dalvik.system.DexFile");// 从DexFile类中获取字段mCookie Field mCookieField = DexFileClass.getDeclaredField("mCookie");// 设置权限mCookieField.setAccessible(true);// 获取字段mFileNameField mFIleNameField = DexFileClass.getDeclaredField("mFileName");// 设置权限mFIleNameField.setAccessible(true);// 从DexFile类中获取getClassNameList方法Method getClassNameListMethod = DexFileClass.getDeclaredMethod("getClassNameList",Object.class);// 设置权限getClassNameListMethod.setAccessible(true);// 遍历dexElements,dexElement里面有dexFilefor(Object dexElementobj:dexElementsArratobj){// 获取dexfile对象Object dexfileObj = dexFileField.get(dexElementobj);// 获取mCookie对象Object mCookieobj = mCookieField.get(dexfileObj);// 获取mFileName对象String mFileNameobj = (String) mFIleNameField.get(dexfileObj);// 调用getClassNameList方法获取类列表String[] classList = (String[]) getClassNameListMethod.invoke(null,mCookieobj);for(String classname:classList){// 打印信息Log.e("classlist",classLoader.toString()+"---"+mFileNameobj+"---"+classname);}}
}
调用getClassListInClassLoader()
getClassListInClassLoader(dexClassLoader)
成功获取到了dexClassLoader
类加载器中可以加载的类