国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Java ClassLoader基礎(chǔ)及加載不同依賴 Jar 中的公共類(lèi)

2019-11-14 21:03:46
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
java ClassLoader基礎(chǔ)及加載不同依賴 Jar 中的公共類(lèi)

轉(zhuǎn)載自:最新內(nèi)容及最清晰格式請(qǐng)見(jiàn)http://www.trinea.cn/android/java-loader-common-class/

本文主要介紹 ClassLoader 的基礎(chǔ)知識(shí),ClassLoader 如何動(dòng)態(tài)加載 Jar,ClassLoader 隔離問(wèn)題及如何加載不同 Jar 中的公共類(lèi)。

本文工程開(kāi)源地址見(jiàn):Java Dynamic Load Jar@Github,Clone 以后直接以 Java application去運(yùn)行 java-dynamic-loader-host 工程即可。

其實(shí)本文只是 Android 插件化的一個(gè)引子,做過(guò) Android 插件化的同學(xué),可以試試對(duì)于 Android Support 包中的 FragmentActivity 和 ActionBarActivity 怎么像一般的 Activity 一樣被代理,挺有意思。

1. ClassLoader 的基礎(chǔ)知識(shí)無(wú)論是 JVM 還是 Dalvik 都是通過(guò) ClassLoader 去加載所需要的類(lèi),而 ClassLoader 加載類(lèi)的方式常稱為雙親委托,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;}

從上面加載類(lèi)的順序中我們可以知道,loadClass 會(huì)先看這個(gè)類(lèi)是不是已經(jīng)被 loaded 過(guò),沒(méi)有的話則去他的 parent 去找,如此遞歸,稱之為雙親委托。

2. 動(dòng)態(tài)加載 JarJava 中動(dòng)態(tài)加載 Jar 比較簡(jiǎn)單,如下:

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

表示加載 libs 下面的 jar1.jar,其中 parentLoader 就是上面1中的 parent,可以為當(dāng)前的 ClassLoader。

3. ClassLoader 隔離問(wèn)題大家覺(jué)得一個(gè)運(yùn)行程序中有沒(méi)有可能同時(shí)存在兩個(gè)包名和類(lèi)名完全一致的類(lèi)?JVM 及 Dalvik 對(duì)類(lèi)唯一的識(shí)別是 ClassLoader id + PackageName + ClassName,所以一個(gè)運(yùn)行程序中是有可能存在兩個(gè)包名和類(lèi)名完全一致的類(lèi)的。并且如果這兩個(gè)”類(lèi)”不是由一個(gè) ClassLoader 加載,是無(wú)法將一個(gè)類(lèi)的示例強(qiáng)轉(zhuǎn)為另外一個(gè)類(lèi)的,這就是 ClassLoader 隔離。 如 Android 中碰到如下異常

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

當(dāng)碰到這種問(wèn)題時(shí)可以通過(guò) instance.getClass().getClassLoader(); 得到 ClassLoader,看 ClassLoader 是否一樣。

4. 加載不同 Jar 包中公共類(lèi)現(xiàn)在 Host 工程包含了 common.jar, jar1.jar, jar2.jar,并且 jar1.jar 和 jar2.jar 都包含了 common.jar,我們通過(guò) ClassLoader 將 jar1, jar2 動(dòng)態(tài)加載進(jìn)來(lái),這樣在 Host 中實(shí)際是存在三份 common.jar,如下圖:Class Diagram我們?cè)趺幢WC common.jar 只有一份而不會(huì)造成上面3中提到的 ClassLoader 隔離的問(wèn)題呢,其實(shí)很簡(jiǎn)單,有三種方式:第一種:我們只要讓加載 jar1 和 jar2 的 ClassLoader 的 parent 為同一個(gè) ClassLoader,并且該 ClassLoader 加載過(guò) common.jar,通過(guò)上面 1 中我們知道根據(jù)雙親委托,最后都會(huì)首先被 parentClassLoader加載。

第二種:我們重寫(xiě) jar1 和 jar2 的 ClassLoader,在 loadClass 函數(shù)中我們先去某個(gè)含有 common.jar 的 ClassLoader 中 load 即可,其實(shí)就是把上面的 parentClassLoader 換掉了而已。

第三種:在生成 jar1 和 jar2 時(shí)把 common.jar 去掉,只保留 host 中一份,以 host ClassLoader 為 parentClassLoader 即可。具體可見(jiàn)代碼:JarClassLoader

大家測(cè)試后會(huì)發(fā)現(xiàn)對(duì)于 Java 是正常的,而方式一和方式二對(duì)于 Android 卻失敗,具體原因下次再說(shuō)吧


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 河西区| 安图县| 新宁县| 弋阳县| 互助| 新巴尔虎左旗| 曲靖市| 同德县| 双城市| 曲沃县| 信宜市| 汉源县| 绥中县| 呼伦贝尔市| 政和县| 吴川市| 峨山| 东港市| 同德县| 商水县| 东台市| 呼图壁县| 桂阳县| 科技| 磐石市| 龙海市| 盈江县| 体育| 恩平市| 宿松县| 朝阳县| 西乌| 伊通| 咸宁市| 乐安县| 城固县| 疏附县| 通山县| 班戈县| 新和县| 陆川县|