在Android的App中动态的加载Java类
原文的地址: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类的更多相关文章
- 使用javassist运行时动态重新加载java类及其他替换选择
在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...
- 《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?
Java虚拟机是如何加载Java类的? 这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. ...
- Android系统下的动态Dex加载与app速度优化
1 问题 在Android系统中,一个App的所有代码都在一个Dex文件里面.Dex是一个类似Jar的存储了多有Java编译字节码的归档文件.因为Android系统使用Dalvik虚拟机,所以需要把 ...
- Android系统下的动态Dex加载
1 问题在Android系统中,一个App的所有代码都在一个Dex文件里面.Dex是一个类似Jar的存储了多有Java编译字节码的归档文件.因为Android系统使用Dalvik虚拟机,所以需要把使用 ...
- 03 Java 虚拟机是如何加载 Java 类的
Java 引用类型 Java 中的引用类型细分为四种:类,接口,数组类和泛型参数. 因为泛型参数会在编译过程中被擦除,所以 Java 虚拟机实际上只有前三种.数组类是由 Java 虚拟机直接生成的,其 ...
- 怎么在 html 中 动态的加载一个 script
var script = document.createElement( 'script' );script.type = 'text/javascript';script.src = bodyStr ...
- log4j中Logger.getLogger()加载一个类提示错误
转载自:https://blog.csdn.net/q3229270/article/details/77986687 ----------------------------- 错误提示如下:The ...
- IDEA 配置Jrebet 自动加载Java类,
官方文档地址: http://manuals.zeroturnaround.com/jrebel/ide/intellij.html#installation 过期激活 https://blog.cs ...
- Java_动态重新加载Class总结
在此记载Java动态重新加载Class的点点滴滴,实现之前也在网上看了很多文章,但发现不是很清晰,后来发现总结,看源码实现还是最靠谱. 直接上代码: package com.lkb.autoCode. ...
随机推荐
- JavaWeb随笔整理
JavaWeb随笔整理 为方便阅读,故整理了相关学习笔记 前端相关 HTML CSS JavaScript BootStrap 数据库相关 MySQL基础 MySQL表的约束和数据库设计 MySQL多 ...
- threejs 基础概要
threejs 基础概要 点击查看官方文档 下面是翻译的内容(稍作修改) 先了解一下Three.js应用程序的结构.Three.js应用程序需要创建一堆对象并将它们连接在一起.下图表示一个小three ...
- linux_MYSQL 数据库自动备份并压缩和删除历史备份
1. 创建shell脚本 #! /bin/bash# MySQL用户user="root"# MySQL密码userPWD="123456789"# 需要定时备 ...
- 🚩数分工作了三年,我干了件很酷的事情
从17年毕业来,一直都在干数据分析的工作.和很多转行的小伙伴一样,没有对口的科班学习,摸不清数据分析具体情况,起初充满着很多迷茫. 在刚开始的1年半中,都是自己从淘宝买些课程,最多时,网盘放了4-5T ...
- Python之内存泄漏和内存溢出
预习知识:python之MRO和垃圾回收机制 一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题.对于一个用 python 实现的,长期运行的后台 ...
- c语言链表从本地文件中读取和写入数据
1 typedef struct Data{ 2 40 char *name; 3 41 char *IDCARD; 4 42 char *job_id; 5 43 char *length; 6 4 ...
- ASPOSE.Cells & ASPOSE.Words 操纵Excel和Word文档的 .NET Core 实例
Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,它提供的原生API可以对Word.Excel.PDF.Powerpoint.Outlook.CAD.图片.3D.ZI ...
- 【linux】驱动-3-字符设备驱动
目录 前言 3. 字符设备驱动 3.1 Linux设备分类 3.2 设备相关概念 3.2.1 设备号 3.2.2 设备节点 3.2.3 APP open 文件理解 ** 3.3 数据结构 3.3.1 ...
- 全网最详细的Linux命令系列-cp命令
cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...
- 「最强」Lettuce 已支持 Redis6 客户端缓存
Redis 客户端缓存 缓存的解决方案一般有两种: [L1] 内存缓存(如 Caffeine.Ehcache) -- 速度快,进程内可用,但重启缓存丢失,出现缓存雪崩的问题. [L2]集中式缓存(如 ...