<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>


       To build a better world !

    Android類(lèi)動(dòng)態(tài)加載技術(shù)

    轉(zhuǎn)載請(qǐng)注明出處:http://www.tkk7.com/zh-weir/archive/2011/10/29/362294.html 

    Android類(lèi)動(dòng)態(tài)加載技術(shù)

    Android應(yīng)用開(kāi)發(fā)在一般情況下,常規(guī)的開(kāi)發(fā)方式和代碼架構(gòu)就能滿足我們的普通需求。但是有些特殊問(wèn)題,常常引發(fā)我們進(jìn)一步的沉思。我們從沉思中產(chǎn)生頓悟,從而產(chǎn)生新的技術(shù)形式。

    如何開(kāi)發(fā)一個(gè)可以自定義控件的Android應(yīng)用?就像eclipse一樣,可以動(dòng)態(tài)加載插件;如何讓Android應(yīng)用執(zhí)行服務(wù)器上的不可預(yù)知的代碼?如何對(duì)Android應(yīng)用加密,而只在執(zhí)行時(shí)自解密,從而防止被破解?……

    熟悉Java技術(shù)的朋友,可能意識(shí)到,我們需要使用類(lèi)加載器靈活的加載執(zhí)行的類(lèi)。這在Java里已經(jīng)算是一項(xiàng)比較成熟的技術(shù)了,但是在Android中,我們大多數(shù)人都還非常陌生。

    類(lèi)加載機(jī)制

           Dalvik虛擬機(jī)如同其他Java虛擬機(jī)一樣,在運(yùn)行程序時(shí)首先需要將對(duì)應(yīng)的類(lèi)加載到內(nèi)存中。而在Java標(biāo)準(zhǔn)的虛擬機(jī)中,類(lèi)加載可以從class文件中讀取,也可以是其他形式的二進(jìn)制流。因此,我們常常利用這一點(diǎn),在程序運(yùn)行時(shí)手動(dòng)加載Class,從而達(dá)到代碼動(dòng)態(tài)加載執(zhí)行的目的。

           然而Dalvik虛擬機(jī)畢竟不算是標(biāo)準(zhǔn)的Java虛擬機(jī),因此在類(lèi)加載機(jī)制上,它們有相同的地方,也有不同之處。我們必須區(qū)別對(duì)待。

           例如,在使用標(biāo)準(zhǔn)Java虛擬機(jī)時(shí),我們經(jīng)常自定義繼承自ClassLoader的類(lèi)加載器。然后通過(guò)defineClass方法來(lái)從一個(gè)二進(jìn)制流中加載Class。然而,這在Android里是行不通的,大家就沒(méi)必要走彎路了。參看源碼我們知道,AndroidClassLoaderdefineClass方法具體是調(diào)用VMClassLoaderdefineClass本地靜態(tài)方法。而這個(gè)本地方法除了拋出一個(gè)“UnsupportedOperationException”之外,什么都沒(méi)做,甚至連返回值都為空。

    static void Dalvik_java_lang_VMClassLoader_defineClass(const u4* args,

        JValue
    * pResult)

    {

        Object
    * loader = (Object*) args[0];

        StringObject
    * nameObj = (StringObject*) args[1];

        
    const u1* data = (const u1*) args[2];

        
    int offset = args[3];

        
    int len = args[4];

        Object
    * pd = (Object*) args[5];

        
    char* name = NULL;

     

        name 
    = dvmCreateCstrFromString(nameObj);

        LOGE(
    "ERROR: defineClass(%p, %s, %p, %d, %d, %p)\n",

            loader, name, data, offset, len, pd);

        dvmThrowException(
    "Ljava/lang/UnsupportedOperationException;",

            
    "can't load this type of class file");

     

        free(name);

        RETURN_VOID();

    }


    Dalvik
    虛擬機(jī)類(lèi)加載機(jī)制

           那如果在Dalvik虛擬機(jī)里,ClassLoader不好使,我們?nèi)绾螌?shí)現(xiàn)動(dòng)態(tài)加載類(lèi)呢?Android為我們從ClassLoader派生出了兩個(gè)類(lèi):DexClassLoaderPathClassLoader。其中需要特別說(shuō)明的是PathClassLoader中一段被注釋掉的代碼:

    /* --this doesn't work in current version of Dalvik--

        if (data != null) {

            System.out.println("--- Found class " + name

                + " in zip[" + i + "] '" + mZips[i].getName() + "'");

            int dotIndex = name.lastIndexOf('.');

            if (dotIndex != -1) {

                String packageName = name.substring(0, dotIndex);

                synchronized (this) {

                    Package packageObj = getPackage(packageName);

                    if (packageObj == null) {

                        definePackage(packageName, null, null,

                                null, null, null, null, null);

                    }

                }

            }

     

            return defineClass(name, data, 0, data.length);

        }

    */



           這從另一方面佐證了defineClass函數(shù)在Dalvik虛擬機(jī)里確實(shí)是被閹割了。而在這兩個(gè)繼承自ClassLoader的類(lèi)加載器,本質(zhì)上是重載了ClassLoaderfindClass方法。在執(zhí)行loadClass時(shí),我們可以參看ClassLoader部分源碼:

    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;

    }


           因此DexClassLoaderPathClassLoader都屬于符合雙親委派模型的類(lèi)加載器(因?yàn)樗鼈儧](méi)有重載loadClass方法)。也就是說(shuō),它們?cè)诩虞d一個(gè)類(lèi)之前,回去檢查自己以及自己以上的類(lèi)加載器是否已經(jīng)加載了這個(gè)類(lèi)。如果已經(jīng)加載過(guò)了,就會(huì)直接將之返回,而不會(huì)重復(fù)加載。

           DexClassLoaderPathClassLoader其實(shí)都是通過(guò)DexFile這個(gè)類(lèi)來(lái)實(shí)現(xiàn)類(lèi)加載的。這里需要順便提一下的是,Dalvik虛擬機(jī)識(shí)別的是dex文件,而不是class文件。因此,我們供類(lèi)加載的文件也只能是dex文件,或者包含有dex文件的.apk.jar文件。

            
    也許有人想到,既然DexFile可以直接加載類(lèi),那么我們?yōu)槭裁催€要使用ClassLoader的子類(lèi)呢?DexFile在加載類(lèi)時(shí),具體是調(diào)用成員方法loadClass或者loadClassBinaryName。其中loadClassBinaryName需要將包含包名的類(lèi)名中的”.”轉(zhuǎn)換為”/”。我們看一下loadClass代碼就清楚了:


    public Class loadClass(String name, ClassLoader loader) {

            String slashName 
    = name.replace('.''/');

            
    return loadClassBinaryName(slashName, loader);

    }

           在這段代碼前有一段注釋?zhuān)厝£P(guān)鍵一部分就是說(shuō):If you are not calling this from a class loader, this is most likely not going to do what you want. Use {@link Class#forName(String)} instead. 這就是我們需要使用ClassLoader子類(lèi)的原因。至于它是如何驗(yàn)證是否是在ClassLoader中調(diào)用此方法的,我沒(méi)有研究,大家如果有興趣可以繼續(xù)深入下去。

           有一個(gè)細(xì)節(jié),可能大家不容易注意到。PathClassLoader是通過(guò)構(gòu)造函數(shù)new DexFile(path)來(lái)產(chǎn)生DexFile對(duì)象的;而DexClassLoader則是通過(guò)其靜態(tài)方法loadDexpath, outpath, 0)得到DexFile對(duì)象。這兩者的區(qū)別在于DexClassLoader需要提供一個(gè)可寫(xiě)的outpath路徑,用來(lái)釋放.apk包或者.jar包中的dex文件。換個(gè)說(shuō)法來(lái)說(shuō),就是PathClassLoader不能主動(dòng)從zip包中釋放出dex,因此只支持直接操作dex格式文件,或者已經(jīng)安裝的apk(因?yàn)橐呀?jīng)安裝的apkcache中存在緩存的dex文件)。而DexClassLoader可以支持.apk.jar.dex文件,并且會(huì)在指定的outpath路徑釋放出dex文件。

           另外,PathClassLoader在加載類(lèi)時(shí)調(diào)用的是DexFileloadClassBinaryName,而DexClassLoader調(diào)用的是loadClass。因此,在使用PathClassLoader時(shí)類(lèi)全名需要用”/”替換”.”


    實(shí)際操作

           這一部分比較簡(jiǎn)單,因此我就不贅言了。只是簡(jiǎn)單的說(shuō)下。

           可能使用到的工具都比較常規(guī):javacdxeclipse等。其中dx工具最好是指明--no-strict,因?yàn)?/span>class文件的路徑可能不匹配。

           加載好類(lèi)后,通常我們可以通過(guò)Java反射機(jī)制來(lái)使用這個(gè)類(lèi)。但是這樣效率相對(duì)不高,而且老用反射代碼也比較復(fù)雜凌亂。更好的做法是定義一個(gè)interface,并將這個(gè)interface寫(xiě)進(jìn)容器端。待加載的類(lèi),繼承自這個(gè)interface,并且有一個(gè)參數(shù)為空的構(gòu)造函數(shù),以使我們能夠通過(guò)ClassnewInstance方法產(chǎn)生對(duì)象。然后將對(duì)象強(qiáng)制轉(zhuǎn)換為interface對(duì)象,于是就可以直接調(diào)用成員方法了。


    關(guān)于代碼加密的一些設(shè)想

           最初設(shè)想將dex文件加密,然后通過(guò)JNI將解密代碼寫(xiě)在Native層。解密之后直接傳上二進(jìn)制流,再通過(guò)defineClass將類(lèi)加載到內(nèi)存中。

           現(xiàn)在也可以這樣做,但是由于不能直接使用defineClass,而必須傳文件路徑給dalvik虛擬機(jī)內(nèi)核,因此解密后的文件需要寫(xiě)到磁盤(pán)上,增加了被破解的風(fēng)險(xiǎn)。

           Dalvik虛擬機(jī)內(nèi)核僅支持從dex文件加載類(lèi)的方式是不靈活的,由于沒(méi)有非常深入的研究?jī)?nèi)核,我不能確定是Dalvik虛擬機(jī)本身不支持還是Android在移植時(shí)將其閹割了。不過(guò)相信Dalvik或者是Android開(kāi)源項(xiàng)目都正在向能夠支持raw數(shù)據(jù)定義類(lèi)方向努力。

           我們可以在文檔中看到Google說(shuō):Jar or APK file with "classes.dex". (May expand this to include "raw DEX" in the future.);在AndroidDalvik源碼中我們也能看到RawDexFile的身影(不過(guò)沒(méi)有具體實(shí)現(xiàn))。

           RawDexFile出來(lái)之前,我們都只能使用這種存在一定風(fēng)險(xiǎn)的加密方式。需要注意釋放的dex文件路徑及權(quán)限管理,另外,在加載完畢類(lèi)之后,除非出于其他目的否則應(yīng)該馬上刪除臨時(shí)的解密文件。


    轉(zhuǎn)載請(qǐng)注明出處:http://www.tkk7.com/zh-weir/archive/2011/10/29/362294.html 

    posted on 2011-10-29 21:51 zh.weir 閱讀(37952) 評(píng)論(25)  編輯  收藏 所屬分類(lèi): Android軟件安全

    評(píng)論

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2011-11-30 13:25 android動(dòng)態(tài)加載

    更好的做法是定義一個(gè)interface,并將這個(gè)interface寫(xiě)進(jìn)容器端
    >容器端做interface的強(qiáng)制類(lèi)型轉(zhuǎn)換時(shí)出現(xiàn)異常,java.lang.ClassCastException:
    不知道您有沒(méi)有遇到?  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2011-11-30 20:52 zh-weir


    檢查一下,是否在Host端和Plugin端分別都定義了liangzijian這個(gè)接口。如果都定義了,且均被編譯進(jìn)了字節(jié)碼文件中就會(huì)發(fā)生類(lèi)似的問(wèn)題。原因是 newInstance生成的對(duì)象實(shí)現(xiàn)的是Plugin端的liangzijian接口,而你想要轉(zhuǎn)化的是Host端的liangzijian接口。兩個(gè)接口雖然名字相同,甚至可能包名也一樣,但是它們是由不同的類(lèi)加載器加載的,所以不同不能實(shí)現(xiàn)轉(zhuǎn)化。

    解決辦法是不要將liangzijian接口編譯進(jìn)Plugin端的字節(jié)碼中。具體做法是導(dǎo)入liangzijian接口的jar庫(kù)時(shí),不要使用添加外部jar庫(kù),而應(yīng)使用user library。后一種方式不會(huì)將庫(kù)中的類(lèi)編譯進(jìn)字節(jié)碼中,而是在運(yùn)行時(shí)去動(dòng)態(tài)鏈接。
      回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2011-12-01 15:15 android動(dòng)態(tài)加載

    @zh-weir
    問(wèn)題解決了,需要注意兩點(diǎn):
    1、Host端和Plugin端interface文件的包名需要一致
    2、jar文件打包時(shí)不要包含interface文件

    另外,DexClassLoader的最后一個(gè)參數(shù)使用getClassLoader()或者VMStack.getCallingClassLoader();  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2011-12-02 10:31 zephyranthes

    有點(diǎn)問(wèn)題想請(qǐng)教樓主,之前使用dexclassloader想加載另一個(gè)apk的activity會(huì)出現(xiàn)activitynotfoundexception異常,似乎這種方式行不通.

    后來(lái)想到是不時(shí)只是寫(xiě)一個(gè)jni的native activity,當(dāng)apk運(yùn)行時(shí),會(huì)先運(yùn)行這個(gè)jni so,然后該so生成解密的dex文件,再通過(guò)dexclassloader加載該dex中的activity?

    麻煩樓主解答,謝謝  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-02-17 23:59 passbye

    反復(fù)反復(fù)反復(fù)反復(fù)反復(fù)反復(fù)反復(fù)反復(fù)反復(fù)  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-02-18 00:01 pass

    請(qǐng)問(wèn)對(duì)于(對(duì)Android應(yīng)用加密,而只在執(zhí)行時(shí)自解密,從而防止被破解?)這句話該如何理解,是對(duì)本地的(已安裝好的)apk加密還是什么操作?請(qǐng)大家指教。謝謝,希望大家共同進(jìn)步。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-02-28 09:19 zh_weir

    @pass

    由于apk應(yīng)用需要經(jīng)過(guò)Android系統(tǒng)的解析和安裝,因此是不能對(duì)它進(jìn)行直接加密的哦。那樣會(huì)導(dǎo)致apk無(wú)法安裝或者無(wú)法運(yùn)行。

    我的意思是將核心代碼抽取出來(lái),作為二進(jìn)制資源,由APK應(yīng)用在運(yùn)行時(shí)動(dòng)態(tài)加載。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-08 20:05 林風(fēng)

    @android動(dòng)態(tài)加載
    可否留個(gè)郵箱,交流一下,My Email --xk1411@139.com.  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-09 17:06 zh.weir

    @林風(fēng)

    呵呵,其實(shí)右上方的公告里有寫(xiě)。zh.weir@gmail.com 。

    歡迎交流!  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-26 10:04 ljj

    小弟現(xiàn)正開(kāi)發(fā)一個(gè)這樣一個(gè)應(yīng)用,這個(gè)應(yīng)用做為主應(yīng)用,只需要實(shí)現(xiàn)一些基本的功能就行,
    如果要擴(kuò)展功能的話,就通過(guò)開(kāi)發(fā)一些小插件來(lái)實(shí)現(xiàn)

    實(shí)現(xiàn)原理是這樣的:
    主應(yīng)用(Host)定義一個(gè)接口:
    public abstract interface IExtension{
    void method1(WebView webview,....);
    void method2();


    public class AbstractExtension extends ContextWrapper implements IExtension{
    .....
    基本是對(duì)IExtension的空實(shí)現(xiàn)

    }


    這里應(yīng)用反射來(lái)實(shí)例化一個(gè)插件:
    ClassLoader localExtensionClassLoader = context.createPackageContext(this.mPackageName,Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY).getClassLoader();
    ClassLoader localSystemClassLoader = OlivePackageManager.getSystemClassLoader();

    ClassLoaderWrapper localClassLoaderWrapper = new ClassLoaderWrapper(localExtensionClassLoader, localSystemClassLoader);

    String localClassName = String.valueOf(this.mPackageName) + ".Extension";
    Class<?> localClass = localClassLoaderWrapper.loadClass(localClassName);

    Constructor<?> localConstructor = localClass.getConstructor( new Class[]{Context.class} );
    localConstructor.setAccessible(true);

    Object instance = localConstructor.newInstance( new Object[]{context} );




    public class ClassLoaderWrapper extends ClassLoader{

    public ClassLoaderWrapper(ClassLoader extensionClassLoader, ClassLoader systemClassLoader) {
    super(systemClassLoader);
    this.mLoader = extensionClassLoader;
    }

    protected Class<?> findClass(String className) throws ClassNotFoundException {
    System.out.println("mLoader type === " + mLoader.toString());
    Class<?> localClass = null;

    if (localClass == null){
    //這個(gè)地方,就是這個(gè)地方,加載失敗
    localClass = this.mLoader.loadClass(className);
    }

    System.out.println("mLoader.loadClass============="+localClass);
    return localClass;
    }

    protected Class<?> loadClass(String className, boolean paramBoolean){
    Class<?> localClass = null;
    try {
    localClass = getParent().loadClass(className);
    } catch (ClassNotFoundException localClassNotFoundException) {
    localClass = findLoadedClass(className);

    if (localClass == null) {
    try {
    localClass = findClass(className);
    } catch (ClassNotFoundException e) {
    }
    }
    }

    return localClass;
    }




    在插件工程中:
    public class Extension extends AbstractExtension{
    ...實(shí)現(xiàn)IExtension接口


    這樣做的話,插件工程必須加入對(duì)主工程(Host)的引用



    思想是好的,但是問(wèn)題出來(lái)了,我主應(yīng)用的類(lèi)加載器總是load不到插件工程的Extension類(lèi),
    但是如果我的插件工程里面不extends AbstractExtension 的話,是ok的,但是不繼承,就失去了意義。

    分析原因:
    public ClassLoaderWrapper(ClassLoader extensionClassLoader, ClassLoader systemClassLoader) {
    super(systemClassLoader);
    this.mLoader = extensionClassLoader;
    }
    這個(gè)構(gòu)造函數(shù)里面,extensionClassLoader作為父類(lèi)加載器,extensionClassLoader作為插件的類(lèi)加載器,

    loadClass方法里面,先用systemClassLoader加載,應(yīng)該是加載不到插件的Extension的,那么接下來(lái)就使用extensionClassLoader來(lái)加載,這個(gè)時(shí)候extensionClassLoader與插件的Extension是同一Context,理所當(dāng)然能夠加載到,但是問(wèn)題是Extension extends AbstractExtension,它肯定是加載不到AbstractExtension,導(dǎo)致插件的Extension也加載失敗

    這個(gè)問(wèn)題困擾了我多日了,希望哪位給個(gè)意見(jiàn),幫助分析一下,我應(yīng)該怎么做?

      回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-26 15:09 zh-weir

    @ljj

    之前的評(píng)論有說(shuō):

    需要注意兩點(diǎn):
    1、Host端和Plugin端interface文件的包名需要一致
    2、jar文件打包時(shí)不要包含interface文件

    另外,DexClassLoader的最后一個(gè)參數(shù)使用getClassLoader()或者VMStack.getCallingClassLoader();  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-26 15:39 ljj

    樓主,我用的是自定的classloader,沒(méi)用DexClassLoader,我現(xiàn)在就是要?jiǎng)討B(tài)加載插件的
    類(lèi)Class<?> localClass = localClassLoaderWrapper.loadClass(localClassName);但是在自定義的classloader中的@Override
    protected Class<?> findClass(String className)
    throws ClassNotFoundException {
    System.out.println("mLoader type === " + mLoader.toString());
    Class<?> localClass = null;
    if ((this.mLoader instanceof PathClassLoader)){
    //localClass = a(paramString);

    }
    if (localClass == null) {
    // 這個(gè)地方,就是這個(gè)地方,加載失敗
    localClass = this.mLoader.loadClass(className);
    }

    System.out.println("mLoader.loadClass=============" + localClass);
    return localClass;
    }

    我沒(méi)有用到j(luò)ar包,謝謝  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-26 16:45 zh-weir

    @ljj

    沒(méi)有用到j(luò)ar,那你是從哪個(gè)文件里load類(lèi)?這點(diǎn)需要明確。個(gè)人認(rèn)為,第一可能是沒(méi)有指明從哪個(gè)文件load類(lèi);第二是IExtension被不同的類(lèi)加載器加載了兩次,這樣兩個(gè)IExtension雖然名字相同、包名相同,但是它們是不同的類(lèi)。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-26 17:25 ljj

    @zh-weir

    我是要加載插件中的類(lèi)

    String localClassName = String.valueOf(packageName)+ ".Extension";


    其中ClassLoaderWrapper 是自定義的classloader
    IExtension只在主host定義的接口
    在主host基本是對(duì)IExtension的空實(shí)現(xiàn)

    在插件中具體實(shí)現(xiàn)

    ClassLoaderWrapper localClassLoaderWrapper = new ClassLoaderWrapper (localExtensionClassLoader , localSystemClassLoader );
    String localClassName = String.valueOf(this.c)+ ".Extension";
    Class<?> localClass = localClassLoaderWrapper.loadClass(localClassName);


      回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-26 17:37 zh.weir

    @ljj

    String localClassName = String.valueOf(this.c)+ ".Extension";
    Class<?> localClass = localClassLoaderWrapper.loadClass(localClassName);

    這是load插件中的類(lèi)嗎?你的“插件”存在于哪?是安裝好的apk,還是未安裝的apk,還是jar或者dex文件?總需要一個(gè)路徑的。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-27 08:17 ljj

    @zh-weir
    我的插件是已安裝好的apk,


    String localClassName = String.valueOf(this.c)+ ".Extension";
    Class<?> localClass = localClassLoaderWrapper.loadClass(localClassName);


    localClassName 是要去動(dòng)態(tài)加載的插件中的類(lèi)名,現(xiàn)在就是加載不上,
    自定義的classloader中

    @Override
    protected Class<?> findClass(String className)
    throws ClassNotFoundException {
    System.out.println("mLoader type === " + mLoader.toString());
    Class<?> localClass = null;
    if ((this.mLoader instanceof PathClassLoader)){
    //localClass = a(paramString);

    }
    if (localClass == null) {
    // 這個(gè)地方,就是這個(gè)地方,加載失敗
    localClass = this.mLoader.loadClass(className);
    }

    System.out.println("mLoader.loadClass=============" + localClass);
    return localClass;
    }  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-27 19:54 zh-weir

    又看了一下你的代碼。首先應(yīng)該是AbstractExtension這個(gè)類(lèi)沒(méi)有加載到。這個(gè)類(lèi),理論上應(yīng)該是由Host端的類(lèi)加載器加載好的。所以問(wèn)題是,plugin端可能并沒(méi)有發(fā)現(xiàn)由host端加載好的AbstractExtension類(lèi)。分析了可能的原因,覺(jué)得ClassLoader localSystemClassLoader = OlivePackageManager.getSystemClassLoader();這個(gè)Classloader可能并不是ClassLoader localExtensionClassLoader = context.createPackageContext(this.mPackageName,Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY).getClassLoader(); 這個(gè)ClassLoader的parent……  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-27 20:14 ljj

    我把插件工程 和主host 的代碼發(fā)到你郵箱了,幫看下吧,謝謝!  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-03-29 08:34 zh-weir

    不好意思,我可能周末才有時(shí)間看你的這份代碼哦……
    辦公室不讓收外部郵箱郵件,業(yè)余時(shí)間又少得可憐。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù)[未登錄](méi) 2012-03-30 14:37 123

    @zh-weir
    按照這個(gè)方法我依然沒(méi)有實(shí)現(xiàn),我用的是PathClassLoader。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù)[未登錄](méi) 2012-03-30 15:04 123

    @zh-weir
    你好,看了你的帖子的確讓我學(xué)到不少。

    但是我的實(shí)現(xiàn)依然存在問(wèn)題。
    以下是我最近一個(gè)項(xiàng)目的需求:我要使我的App(容器端)中某個(gè)固定的View可以替換為其他開(kāi)發(fā)者開(kāi)發(fā)的任意自定義控件。目前利用PathClassLoader已經(jīng)實(shí)現(xiàn)了基本的替換功能。但是存在一個(gè)問(wèn)題,跟上面幾位朋友討論的問(wèn)題相似,在容器端我需要定義一些接口(目前是為了實(shí)現(xiàn)觀察者模式,當(dāng)然以后可能提供更多的接口用以添加容器端和插件端的交互),在插件端的自定義控件可以實(shí)現(xiàn)這些接口,但是根據(jù)樓上提供的方法,依然存在ClassCastException的問(wèn)題。

    以下是我實(shí)現(xiàn)的一些細(xì)節(jié),請(qǐng)LZ看看哪里有問(wèn)題:
    1.我使用的是PathClassLoader,因?yàn)椴寮枰话惭b,所以不用DexClassLoader。
    2.PathClassLoader構(gòu)造的時(shí)候使用的是getSystemClassLoader。
    3.利用Eclipse將接口導(dǎo)出到j(luò)ar(我這里不太清楚是否需要用dx工具將jar里面的.class類(lèi)型轉(zhuǎn)化,我目前的做法是沒(méi)有轉(zhuǎn)化),且不含源文件,插件端可以編譯通過(guò)。  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2012-05-15 19:45 briancol

    博主:請(qǐng)教個(gè)問(wèn)題:
    Dalvik 在加載類(lèi)時(shí), 如果該類(lèi)已被加載,就不會(huì)重新加載。有么有辦法讓dalvik強(qiáng)制重新加載?
    這個(gè)需求的原因是因?yàn)椋?android系統(tǒng)有些自帶類(lèi)會(huì)有各種限制,所以我想通過(guò)寫(xiě)一個(gè)和系統(tǒng)某個(gè)類(lèi)同包名同類(lèi)名的類(lèi),然后讓dalvik加載我的這個(gè)類(lèi),從而突破某些限制。
    博主有沒(méi)有什么思路?  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2013-01-23 14:45 菜鳥(niǎo)1234

    不是很明白,既然有最后解密的過(guò)程,自然就可以找到解密的算法和密鑰,再怎么動(dòng)態(tài)加載類(lèi)又有什么用呢?  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2013-05-08 11:28 chuan

    說(shuō)理清晰,thx  回復(fù)  更多評(píng)論   

    # re: Android類(lèi)動(dòng)態(tài)加載技術(shù) 2013-07-05 14:36 卷起鋪蓋流浪

    @briancol
    我和你在做同樣的事情,如果我想動(dòng)態(tài)替換報(bào)名類(lèi)名都相同的一個(gè)類(lèi),那么這個(gè)類(lèi)dex加載后會(huì)被apk中存在的那個(gè)類(lèi)的實(shí)例覆蓋,沒(méi)有實(shí)現(xiàn)動(dòng)態(tài)加載的意義,請(qǐng)問(wèn)你找到解決方法了么?  回復(fù)  更多評(píng)論   

    公告

    大家好!歡迎光臨我的 Android 技術(shù)博客!



    本博客旨在交流與 Android 操作系統(tǒng)相關(guān)的各種技術(shù)及信息。

    博客內(nèi)的文章會(huì)盡量以開(kāi)源的形式提供給大家,希望我們能相互交流,共同提高!

    有不足之處,請(qǐng)不吝賜教!

    我的郵箱:zh.weir@gmail.com
    我的新浪微博:@囧虎張建偉

     

    導(dǎo)航

    <2011年10月>
    2526272829301
    2345678
    9101112131415
    16171819202122
    23242526272829
    303112345

    統(tǒng)計(jì)

    留言簿(19)

    隨筆分類(lèi)(24)

    隨筆檔案(18)

    文章檔案(1)

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲精品亚洲人成在线观看| 四虎成人精品国产永久免费无码| 亚洲一区二区三区无码国产| 亚洲成人激情小说| 精品亚洲A∨无码一区二区三区| 亚洲欧洲在线观看| 亚洲国产日韩精品| 午夜免费国产体验区免费的| 中文字幕乱码系列免费| 永久看日本大片免费35分钟| 18禁成年无码免费网站无遮挡| 国产三级电影免费观看| 国内精品免费视频自在线| 精品国产污污免费网站aⅴ | 精品国产亚洲一区二区三区在线观看| 亚洲乱码在线视频| 日本免费精品一区二区三区| 久久大香香蕉国产免费网站| 久久国产精品一区免费下载| 无码区日韩特区永久免费系列| 久久受www免费人成_看片中文| 国产伦精品一区二区三区免费下载| 亚洲精品无码AV人在线播放| 亚洲成av人片在线看片| 亚洲人配人种jizz| 一区视频免费观看| 手机看片国产免费永久| 免费99精品国产自在现线| 亚洲精品成人片在线观看| 亚洲成a人在线看天堂无码| 国产成人一区二区三区免费视频| 亚洲午夜无码久久久久| 亚洲日产无码中文字幕| 亚洲一区电影在线观看| 一区二区在线免费视频| 中文字幕av无码无卡免费| 中文字幕不卡亚洲| 亚洲精品国产成人专区| 直接进入免费看黄的网站| 亚洲免费福利视频| 久久亚洲精品无码播放|