续 Android APK免安装启动
此文章描述了通过不替换系统的ClassLoader方式,只是将我们所动态释放的dex文件放入系统的ClassLoader中这种方式实现免安装启动插件APK
有疑问的可以先参看
http://blog.youkuaiyun.com/happyst1990/article/details/51146301
51 @Override
52 protected Class<?> findClass(String name) throws ClassNotFoundException {
53 List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
54 Class c = pathList.findClass(name, suppressedExceptions);
55 if (c == null) {
56 ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
57 for (Throwable t : suppressedExceptions) {
58 cnfe.addSuppressed(t);
59 }
60 throw cnfe;
61 }
62 return c;
63 }
昨天在翻看的时候,无意中留意了一下BaseDexClassLoader的查找类的过程,其中有一个变量
private final DexPathList pathList;
进入看了一下,
304 /**
305 * Finds the named class in one of the dex files pointed at by
306 * this instance. This will find the one in the earliest listed
307 * path element. If the class is found but has not yet been
308 * defined, then this method will define it in the defining
309 * context that this instance was constructed with.
310 *
311 * @param name of class to find
312 * @param suppressed exceptions encountered whilst finding the class
313 * @return the named class or {@code null} if the class is not
314 * found in any of the dex files
315 */
316 public Class findClass(String name, List<Throwable> suppressed) {
317 for (Element element : dexElements) {
318 DexFile dex = element.dexFile;
319
320 if (dex != null) {
321 Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
322 if (clazz != null) {
323 return clazz;
324 }
325 }
326 }
327 if (dexElementsSuppressedExceptions != null) {
328 suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
329 }
330 return null;
331 }
可以发现寻找类的过程是遍历dexElements对象去寻找的。
说道此处可能大家已经明白我想说的是什么,没错,就是让我们手动释放出来的dex加入到此处。
如何获取到dexElements变量,并将其合并,然后设置到PathClassLoader中的过程就不写了,具体如何做请参考上一篇中的通过反射获取变量。