原文的地址:http://yenliangl.blogspot.com/2009/11/dynamic-loading-of-classes-in-your.html

我正在编写一个应用程序能够加载别人开发的应用插件。对于应用程序思路的实现,我首先想到的是使用 Class.forName 以及java.lang.reflective中的提供的方法。我比较倾向于使用 Class.forName(),像下面一样:

try {
Class<?> handler = Class.forName(handlerClassName);
Method m = handler.getDeclaredMethod(
"addMyPreferences",
Class.forName("android.content.Context"),
Class.forName("android.preference.PreferenceCategory"),
Class.forName("java.lang.String"));
m.invoke(handler.newInstance(), this, mExtraSettingsCategory, defaultValue);
} catch(ClassNotFoundException e) {
// .....
}
// other exceptions that may be thrown by reflective API.

但是经过实践发现,上面的代码会出现ClassNotFoundException的异常。我怎么办?一个比较麻烦的问题在我的脑海里闪现,我猜想是不是别的开发者也会和我遇到同样的问题,于是我就谷歌查询,发现一个文档对我理解:为什么上面的代码会抛出ClassNotFoundException异常非常有帮助(点击这里)。

该文档上说,Java的基本动态加载模块依赖于java的parent-chaild层次结构和ClassLoader类。通过日志打印出类加载的顺序(层次)对于理解类的加载很有帮助。因此,我就这么做了。

ClassLoader cl = this.getClass().getClassLoader();
while (cl != null) {
Log.d(TAG, "====> class loader: " + cl.getClass());
cl = cl.getParent();
}

在我的电脑上,在类加载的时候打印显示加载了2个类分别是 dalvik.system.PathClassLoader类 和 java.lang.BootClassLoader类。最有趣的事情是使用 PathClassLoader类。查看它的文档发现 PathClassLoader类能够接受不同类型的值作为它的构造函数的参数,直接从文档上复制过来看:

public PathClassLoader  (String path, ClassLoader parent)

Creates a PathClassLoader that operates on a given list of files and directories. This method is equivalent to calling PathClassLoader(String, String, ClassLoader) with a null value for the second argument (see description there).

    * Directories containing classes or resources.
* JAR/ZIP/APK files, possibly containing a "classes.dex" file.
* "classes.dex" files.

好啦,基于文档上面的规定说明,我猜测使用apk文件名构造PathClassLoader 类实例,并且这个apk应用是在传递中创建,如下:

PathClassLoader("/data/app/org.startsmall.myapp.apk",
ClassLoader.getSystemClassLoader());

因此,如果我想使用Class.forName()就应该从第三方应用开发者哪里知道要加载的类的名字,并且必须重新构造PathClassLoader 类实例从我的apk应用和第三方应用中加载类,下面是示例代码:

final String apkFiles =
"/data/app/org.startsmall.myapp.apk:" + // myself
// handlers defined by other developers
"/data/app/" + handlerClassName.substring(0, lastDotPos) + ".apk"; dalvik.system.PathClassLoader myClassLoader =
new dalvik.system.PathClassLoader(
apkFiles,
ClassLoader.getSystemClassLoader()); // ... try {
Class<?> handler =
Class.forName(handlerClassName, true, classLoader); // Call reflective APIs. } catch (ClassNotFoundException e) {
// .....
}

经过上面这些经验和错误,我的代码终于可以加载第三方的类和方法,并且可以执行达到预期的效果。

注:翻译的不好,请无视直接看原文。

在Android的App中动态的加载Java类的更多相关文章

  1. 使用javassist运行时动态重新加载java类及其他替换选择

    在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...

  2. 《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?

    Java虚拟机是如何加载Java类的?  这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. ...

  3. Android系统下的动态Dex加载与app速度优化

    1 问题 在Android系统中,一个App的所有代码都在一个Dex文件里面.Dex是一个类似Jar的存储了多有Java编译字节码的归档文件.因为Android系统使用Dalvik虚拟机,所以需要把 ...

  4. Android系统下的动态Dex加载

    1 问题在Android系统中,一个App的所有代码都在一个Dex文件里面.Dex是一个类似Jar的存储了多有Java编译字节码的归档文件.因为Android系统使用Dalvik虚拟机,所以需要把使用 ...

  5. 03 Java 虚拟机是如何加载 Java 类的

    Java 引用类型 Java 中的引用类型细分为四种:类,接口,数组类和泛型参数. 因为泛型参数会在编译过程中被擦除,所以 Java 虚拟机实际上只有前三种.数组类是由 Java 虚拟机直接生成的,其 ...

  6. 怎么在 html 中 动态的加载一个 script

    var script = document.createElement( 'script' );script.type = 'text/javascript';script.src = bodyStr ...

  7. log4j中Logger.getLogger()加载一个类提示错误

    转载自:https://blog.csdn.net/q3229270/article/details/77986687 ----------------------------- 错误提示如下:The ...

  8. IDEA 配置Jrebet 自动加载Java类,

    官方文档地址: http://manuals.zeroturnaround.com/jrebel/ide/intellij.html#installation 过期激活 https://blog.cs ...

  9. Java_动态重新加载Class总结

    在此记载Java动态重新加载Class的点点滴滴,实现之前也在网上看了很多文章,但发现不是很清晰,后来发现总结,看源码实现还是最靠谱. 直接上代码: package com.lkb.autoCode. ...

随机推荐

  1. go http库 设置代理

    func ProxyTest() { proxyAddr := "http://your IP:8080/" httpUrl := "http://your target ...

  2. 通过kubeadm快速部署K8S集群

    kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具. 这个工具能通过两条指令完成一个kubernetes集群的部署: # 创建一个 Master 节点 $ kubeadm i ...

  3. LeetCode-[list-of-depth-lcci]

    特定深度节点链表-求解每一层二叉树从左到右遍历形成的链表 list-of-depth-lcci 这是关于二叉树的问题,遍历每一层的结点并且存在链表中. 可以采取队列类似于广度优先搜索的方法进行搜索.每 ...

  4. 普通的一天,说一个普通的XML

    什么是XML XML全称是Extensible Markup Language,译为"可扩展标记语言",常用来存储和传输信息. XML的结构 我们经常看到的XML文件是这个样子的: ...

  5. 2020年12月-第02阶段-前端基础-Day06

    CSS Day06 定位(position) 理解 能说出为什么要用定位 能说出定位的4种分类 能说出四种定位的各自特点 能说出我们为什么常用子绝父相布局 应用 能写出淘宝轮播图布局 1. CSS 布 ...

  6. 设计模式之建造者模式(BuilderPattern)

    一.意义 将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 说明:复杂对象的构建,比如一个对象有几十个成员属性,那么我们在创建这个对象,并给成员属性赋值时,就会很麻烦.采用 ...

  7. 一次线上MySQL主从延迟排查

    今天早上来上班,发现zabbix一直告警主从延迟,mysql slave Seconds_Behind_Master (mysql.slave_status[Seconds_Behind_Master ...

  8. P1996_约瑟夫问题(JAVA语言)_可能是最简单的解法了!

    思路:使用队列模拟. 判断是否为出圈的数.如果不是,把数加入队列尾部:如果是,输出并删除. 题目背景 约瑟夫是一个无聊的人!!! 题目描述 n个人(n<=100)围成一圈,从第一个人开始报数,数 ...

  9. 利用matplotlib和cmaps根据已有的colormap,重新定义colormap

    算法网上这哥们总结的还可以[1] ,但是使用matplotlib自定义colormap自己掌握的还不够,写在这里 希望达到的目标 使用什么样的颜色,可以自己定义 方便的调用其他人的色标, 使用一部分c ...

  10. Android学习之在Adapter中调用Fragment

    •前言 在学习<第一行代码>,4.5 小节--一个简易版的新闻应用的时候: 在为 RecyclerView 创建适配器的时候: 作者直接在 NewsTitleFragment.java 中 ...