转载自:最新内容及最清晰格式请见 http://www.trinea.cn/android/java-loader-common-class/

本文主要介绍 ClassLoader 的基础知识,ClassLoader 如何动态加载 Jar,ClassLoader 隔离问题及如何加载不同 Jar 中的公共类。

本文工程开源地址见:Java Dynamic Load Jar@Github,Clone 以后直接以 Java Application去运行 java-dynamic-loader-host 工程即可。

其实本文只是 Android 插件化的一个引子,做过 Android 插件化的同学,可以试试对于 Android Support 包中的 FragmentActivity 和 ActionBarActivity 怎么像一般的 Activity 一样被代理,挺有意思。

1. ClassLoader 的基础知识
无论是 JVM 还是 Dalvik 都是通过 ClassLoader 去加载所需要的类,而 ClassLoader 加载类的方式常称为双亲委托,ClassLoader.java 具体代码如下:

protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(className); if (clazz == null) {
try {
clazz = parent.loadClass(className, false);
} catch (ClassNotFoundException e) {
// Don't want to see this.
} if (clazz == null) {
clazz = findClass(className);
}
} return clazz;
}

从上面加载类的顺序中我们可以知道,loadClass 会先看这个类是不是已经被 loaded 过,没有的话则去他的 parent 去找,如此递归,称之为双亲委托。

2. 动态加载 Jar
Java 中动态加载 Jar 比较简单,如下:

URL[] urls = new URL[] {new URL("file:libs/jar1.jar")};
URLClassLoader loader = new URLClassLoader(urls, parentLoader);

表示加载 libs 下面的 jar1.jar,其中 parentLoader 就是上面1中的 parent,可以为当前的 ClassLoader。

3. ClassLoader 隔离问题
大家觉得一个运行程序中有没有可能同时存在两个包名和类名完全一致的类?
JVM 及 Dalvik 对类唯一的识别是 ClassLoader id + PackageName + ClassName,所以一个运行程序中是有可能存在两个包名和类名完全一致的类的。并且如果这两个”类”不是由一个 ClassLoader 加载,是无法将一个类的示例强转为另外一个类的,这就是 ClassLoader 隔离。 如 Android 中碰到如下异常

android.support.v4.view.ViewPager can not be cast to android.support.v4.view.ViewPager

当碰到这种问题时可以通过 instance.getClass().getClassLoader(); 得到 ClassLoader,看 ClassLoader 是否一样。

4. 加载不同 Jar 包中公共类
现在 Host 工程包含了 common.jar, jar1.jar, jar2.jar,并且 jar1.jar 和 jar2.jar 都包含了 common.jar,我们通过 ClassLoader 将 jar1, jar2 动态加载进来,这样在 Host 中实际是存在三份 common.jar,如下图:

我们怎么保证 common.jar 只有一份而不会造成上面3中提到的 ClassLoader 隔离的问题呢,其实很简单,有三种方式:
第一种:我们只要让加载 jar1 和 jar2 的 ClassLoader 的 parent 为同一个 ClassLoader,并且该 ClassLoader 加载过 common.jar,通过上面 1 中我们知道根据双亲委托,最后都会首先被 parentClassLoader加载。

第二种:我们重写 jar1 和 jar2 的 ClassLoader,在 loadClass 函数中我们先去某个含有 common.jar 的 ClassLoader 中 load 即可,其实就是把上面的 parentClassLoader 换掉了而已。

第三种:在生成 jar1 和 jar2 时把 common.jar 去掉,只保留 host 中一份,以 host ClassLoader 为 parentClassLoader 即可。
具体可见代码:JarClassLoader

大家测试后会发现对于 Java 是正常的,而方式一和方式二对于 Android 却失败,具体原因下次再说吧

Java ClassLoader基础及加载不同依赖 Jar 中的公共类的更多相关文章

  1. Java ClassLoader基础及加载不同依赖 Jar 中的公共类(转)

    http://www.iteye.com/topic/1135259 http://www.trinea.cn/android/java-loader-common-class/ http://www ...

  2. Java --ClassLoader创建、加载class、卸载class

    一.java提供了三种ClassLoader对Class进行加载: 1.BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库 ...

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

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

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

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

  5. Java安全之动态加载字节码

    Java字节码 简单说,Java字节码就是.class后缀的文件,里面存放Java虚拟机执行的指令. 由于Java是一门跨平台的编译型语言,所以可以适用于不同平台,不同CPU的计算机,开发者只需要将自 ...

  6. 自定义ClassLoader,用于加载用户JAR包

    最近在考虑C/S结构程序的软件自动升级的实现方式,比如QQ.飞信等都自动升级的功能. 自动升级模块虽然还没有编码完成,但是思路还是比较清晰的. 自动升级过程中,升级文件的JAR包是专门加载到程序中去的 ...

  7. Java 类加载器及加载Class字节码

    参考来源:http://www.cnblogs.com/fingerboy/p/5456371.html       java笔记--理解java类加载器以及ClassLoader类 参考来源:htt ...

  8. Java 类中各成分加载顺序 和 内存中的存放位置

    参加一个笔试,有一个关于类的静态代码块.构造代码块.构造函数的执行顺序的问题.不太清楚,网上百度了一下.在这里记录一下. 一.什么时候会加载类?使用到类中的内容时加载:有三种情况1.创建对象:new ...

  9. 根据配置文件加载js依赖模块(JavaScript面试题)

    面试题目 根据下面的配置文件 module=[ {'name':'jquery','src':'/js/lib/jquery-1.8.3.js'}, {'name':'swfobject','src' ...

随机推荐

  1. [javascript]获取系统时间函数

    var oDate=new Date(); //初始化系统时间函数 alert(oDate.getHours()); //获取时 alert(oDate.getMinutes()); //获取分 al ...

  2. rsync.conf详解

    1.在服务端编辑配置文件 [root@game_intf ~]# more /etc/rsyncd.conf port=8730 log file=/var/log/rsync.log pid fil ...

  3. jvm分析

    是什么 jps   查看所有的jvm进程,包括进程ID,进程启动的路径等等. jstack   观察jvm中当前所有线程的运行情况和线程当前状态. 系统崩溃了?如果java程序崩溃生成core文件,j ...

  4. android 开发赚钱

    原 android 开发赚钱 谁带我去看看世界 发布时间: 2015/06/09 12:05 阅读: 1589 收藏: 37 点赞: 2 评论: 5 开发android也有一年左右了,利用业余时间陆续 ...

  5. CSS3实现文字抹开特效

    CSS: .column-title { color: #9b9b9b; text-shadow: 1px 1px #d4d4d4;}.column-title:hover { color: #5a5 ...

  6. Android Native jni 编程入门

    在某些情况下,java编程已经不能满足我们的需要,比如一个复杂的算法处理,这时候就需要用到jni(java native interface)技术: jni 其实就是java和c/cpp之间进行通信的 ...

  7. 1 Ionic和Hybird应用介绍

    1.Ionic是什么,它和Angular.Cordova有什么关系? Ionic通过整合各种技术和功能使构建Hybird应用更加快速.容易和美观.Ionic生态系统基于Angular和Cordova, ...

  8. Android Stutio -- 编译报错: Error:File path too long on Windows, keep below 240

    原文:http://blog.csdn.net/qq_28195645/article/details/51556975 目录太长,解决办法: 1.将整个project移到更外层的目录,直至没有报错, ...

  9. 关于Mesos和Kubernetes的区别

    这个主题应该和服务发现注册一样,进入视野...

  10. .NET Nancy 详解(四) Self Host

    Self Host 使得Nancy 能够在任意application 中启动,无论是console 还是windows service.这期我们使用的版本是Nancy v0.4.0. Demo 首先看 ...