原文的地址: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. 基于Hi3559AV100 RFCN实现细节解析-(3)系统输入VI分析(HiISP)二 :

    下面随笔系列将对Hi3559AV100 RFCN实现细节进行解析,整个过程涉及到VI.VDEC.VPSS.VGS.VO.NNIE,其中涉及的内容,大家可以参考之前我写的博客: 基于Hi3559AV10 ...

  2. Codeforces Round #683 (Div. 2, by Meet IT)

    A 初始情况\(1\) ~ \(n\)堆分别有 \(1\) ~ \(n\) 个糖果,第\(i\)次操作给除了所选堆的糖果数 \(+ i\), 找到一种方案可以使得所有堆糖果数相同,输出操作次数和每次选 ...

  3. redhat安装python3.7

    下载并解压: 1 wget https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tgz 2 tar -xzvf Python-3.7.2.tgz ...

  4. Mysql在windows环境如何修改密码?

    1.关闭正在运行的MySQL服务. 2. 打开DOS窗口,转到mysql\bin目录. 3. 输入mysqld --skip-grant-tables 回车.--skip-grant-tables 的 ...

  5. P2260 [清华集训2012]模积和 【整除分块】

    一.题目 P2260 [清华集训2012]模积和 二.分析 参考文章:click here 具体的公式推导可以看参考文章.博主的证明很详细. 自己在写的时候问题不在公式推导,公式还是能够比较顺利的推导 ...

  6. 15款NOSQL数据库

    1.MongoDB 介绍 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.主要解决的是海量数据的访问效率问题,为WEB应用提供可扩展的高性能数据存储解决方案.当数据量达到50GB以上 ...

  7. 《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口

    <C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户 ...

  8. MySQL数据库与python交互

    1.安装引入模块 安装mysql模块 pip install PyMySQL; 文件中引入模块 import pymysql 2.认识Connection对象 用于建立与数据库的连接 创建对象:调用c ...

  9. Oauth2协议那些事

    1. 背景 首先,设想一种情境:你平常会使用一款照片存储App(以下照片服务指代),用来将自己喜欢的照片存放在上面以备随时查看.假如有一天,你想要打印其中的某张照片而且你找到了一款打印照片App(以下 ...

  10. 快速了解Web MVC设计模式

    MVC概述 MVC即 Model-View-Controller 的缩写,是按照职责划分模块一种设计模式,其中Model是核心. Model:模型.负责执行实际的业务,包含数据操作,可以向视图推送数据 ...