ClassLoader与DexClassLoader简单例子

来源:互联网 发布:mac world破解版 编辑:程序博客网 时间:2024/06/14 08:40

摘自:《Android 内核剖析》 作者:柯元旦
ClassLoader 类加载器,其作用是动态装载Class文件。每个ClassLoader在初始化时,必须指定Class文件的路径。
在一般情况下,应用程序不需要创建一个全新的ClassLoader对象,而是使用当前环境已经存在的ClassLoader。因为Java的Runtime环境在初始化时,其内部会创建一个ClassLoader对象用于加载Runtime所需的各种Java类。
每个ClassLoader必须有一个父ClassLoader,在装载Class文件时,子ClassLoader会先请求父ClassLoader 加载该文件,只有当其父ClassLoader找不到Class文件时,子ClassLoader才会继续装载该类,这事一种安全机制。

下面是我写的一个基于后面的DexClassLoader的例子,抽取出来的Java小例子:
IntelliJ IDEA 新建工程:PluginDemo
工程新建完毕,新建类PluginClass.java,代码如下:

public class PluginClass {    public PluginClass() {        System.out.println("plugin is init");    }    public int funtion(int a, int b) {        return a + b;    }}

新建Demo.java类,代码如下:

public class Demo {    public static void main(String[] args) {        ClassLoader classLoader = ClassLoader.getSystemClassLoader();        try {            Class<?> clazz = classLoader.loadClass("com.test.PluginClass");            Object obj = clazz.newInstance();            Class[] params = new Class[2];            params[0] = Integer.TYPE;            params[1] = Integer.TYPE;            Method method = obj.getClass().getMethod("funtion", params);            Integer integer = (Integer) method.invoke(obj, 12, 23);            System.out.println("result: " +integer);        } catch (Exception e) {            e.printStackTrace();        }        }}

运行结果输出:
plugin is init
result: 35

DexClassLoader 是集成自 ClassLoader的一个类,集成关系如下:

java.lang.Object   ↳    java.lang.ClassLoader       ↳    dalvik.system.BaseDexClassLoader           ↳    dalvik.system.DexClassLoader

Android 应用程序使用标准的Java编译器编译成Class文件,但最终的APK文件包含的确实dex文件类型。dex文件类型是将所需的所有的Class文件重新打包,优化后的一个新文件。因为要加载这样特殊的Class文件,所以就需要特殊的类装载器,这就是DexClassLoader。
下面是这本书里的DexClassLoader例子:

AndroidStudio新建工程Plugin:
新建类PluginClass,代码如下:

public class PluginClass {    public PluginClass() {        Log.e("tag", "Plugin Class initialized");    }    public int function(int a, int b) {        return a + b;    }}

manifest中添加代码如下:

...<activity android:name=".MainActivity">     <intent-filter>         <action android:name="android.intent.action.MAIN" />         <category android:name="android.intent.category.LAUNCHER" />         <action android:name="com.n.plugin" />      </intent-filter> </activity>...

打好包,安装到手机(不用直接点击运行,这样后面跑宿主程序时,会抛找不到的异常)。

AndroidStudio新建工程Host:
MainActivity中添加代码如下:

private void addPlugin() {        Intent intent = new Intent("com.n.plugin", null);        PackageManager manager = getPackageManager();        List<ResolveInfo> infoList = manager.queryIntentActivities(intent, 0);        if (infoList.isEmpty()) {            return;        }        ResolveInfo info = infoList.get(0);        ActivityInfo activityInfo = info.activityInfo;//      String div = System.getProperty("path.separator"); //多个文件路径之间的分隔符        String packageName = activityInfo.packageName;        String dexPath = activityInfo.applicationInfo.sourceDir;        String dexOutputDir = getApplicationInfo().dataDir;        String libPath = activityInfo.applicationInfo.nativeLibraryDir;        DexClassLoader classLoader = new DexClassLoader(dexPath, dexOutputDir, libPath, getClass().getClassLoader());        try {//          获取Plugin中资源Id的方法//          Resources res = manager.getResourcesForApplication(packageName);//          int id = res.getIdentifier("version", "string", packageName);//          String version = res.getString(id);             Class<?> clazz = classLoader.loadClass(packageName + ".PluginClass");            Object obj = clazz.newInstance();            Class[] params = new Class[2];            params[0] = Integer.TYPE;            params[1] = Integer.TYPE;            Method method = clazz.getMethod("function", params);            Integer integer = (Integer) method.invoke(obj, 12, 23);            Log.e("tag", "--- 获取的结果是 --->" + integer);        } catch (Exception e) {            e.printStackTrace();        }    }

manifest中添加代码如下:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

基本上差不多了。记录一下,方便查阅吧。因为时间长了,老忘……

原创粉丝点击