andfix熱修復(fù)核心代碼解析

前言

https://ke.qq.com/webcourse/index.html#course_id=130901&term_id=100146035&taid=1287279008153429&vid=r1417pykrgc
學(xué)習(xí)了下這個視頻的熱修復(fù)方法葵陵。成功實現(xiàn),但是還是遇到了一些問題陕壹。這里記錄下张弛,幫助大家學(xué)習(xí)臣镣。

代碼分析

首先先簡單的代碼分析一下。

//問題代碼
class Calculator {
    fun calc(): Int {
        return 100 / 0
    }
}

//修復(fù)后代碼
class Calculator {
    @Replace(clazz = "**.Calculator", method = "calc")
    fun calc(): Int {
        return 100
    }
}

原理:替換Art虛擬機中有問題的類的方法茎毁,為修復(fù)后的方法切蟋。(Android 5.0以上)
視頻中已有詳細(xì)介紹,這里就不多贅述了滚停。

fun loadDex(context: Context, dexName: String) {
        val cacheFile: File
        if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
            cacheFile = context.externalCacheDir
        } else {
            cacheFile = context.cacheDir
        }
        val file = File(cacheFile, "dxtest")
        file.deleteOnExit()
        val dexFile = DexFile(File("/storage/emulated/0/", dexName).absolutePath)

        val iterator = dexFile.entries()
        while (iterator.hasMoreElements()) {
            val clazzName = iterator.nextElement()
            val clazz = Class.forName(clazzName)
            //遍歷類方法根據(jù)注解替換
            clazz.declaredMethods.forEach { method ->
                val replacObj = method.getAnnotation(Replace::class.java)
                val replaceClazz = Class.forName(replacObj.clazz)
                val replaceMethod = replaceClazz.getDeclaredMethod(replacObj.method, *method.parameterTypes)
                fixMethod(replaceMethod, method)
            }
        }
    }
....
private external fun fixMethod(replaceMethod: Method, method: Method)

先單獨把修復(fù)后的Calculator.class打包沃粗,利用dx命令打包成out.dex,然后放到/storage/emulated/0/目錄下。

JNIEXPORT void JNICALL
Java_**_fixMethod(JNIEnv *env, jobject thiz,jobject replaceMethod, jobject method) {
    art::mirror::ArtMethod *artReplaceMethod = (art::mirror::ArtMethod *) env->FromReflectedMethod(
            replaceMethod);

    art::mirror::ArtMethod *artMethod = (art::mirror::ArtMethod *) env->FromReflectedMethod(
            method);

    artReplaceMethod->access_flags_ = artMethod->access_flags_;
    artReplaceMethod->declaring_class_ = artMethod->declaring_class_;
    artReplaceMethod->dex_code_item_offset_ = artMethod->dex_code_item_offset_;
    artReplaceMethod->dex_method_index_ = artMethod->dex_method_index_;
    artReplaceMethod->hotness_count_ = artMethod->hotness_count_;
    artReplaceMethod->method_index_ = artMethod->method_index_;
    artReplaceMethod->ptr_sized_fields_.dex_cache_resolved_methods_ = artMethod->ptr_sized_fields_.dex_cache_resolved_methods_;
    artReplaceMethod->ptr_sized_fields_.dex_cache_resolved_types_ = artMethod->ptr_sized_fields_.dex_cache_resolved_types_;
    artReplaceMethod->ptr_sized_fields_.entry_point_from_jni_ = artMethod->ptr_sized_fields_.entry_point_from_jni_;
    artReplaceMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = artMethod->ptr_sized_fields_.entry_point_from_quick_compiled_code_;
}

按照視頻中所說的键畴,把ArtMehod中的變量一一替換最盅。

問題記錄

  1. 困擾我最久的是,訪問sdcard起惕,6.0以上需要手動申請涡贱,這也是自己粗心。視頻中貌似也沒有詳細(xì)提到惹想。而且最讓我頭疼的是logcat中的報錯信息问词。
Caused by: java.io.IOException: No original dex files found for dex location /storage/emulated/0/out.dex
...

于是開始百度,google

image.png

沒有講到權(quán)限問題的嘀粱。
這里值得一提的是曾今在使用VirtualApk插件化技術(shù)的時候激挪,也是遇到這種問題,必須要手到申請下權(quán)限锋叨,不然就會報錯垄分。

后面靈光一閃。添加了權(quán)限申請就好了娃磺。

  1. 視頻中提到了需要使用到art_method.h薄湿,但是里面的東西又不能全部拿來用,因為會涉及到很多其他的頭文件偷卧,所以只要ArtMethod的結(jié)構(gòu)體就好了豺瘤。
    android源碼很大,這里我沒有去下載涯冠,直接訪問http://androidxref.com/7.0.0_r1/xref/art/runtime/art_method.h#mirror
    查看自己需要的內(nèi)容。
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_ART_METHOD_H_A
#define ART_RUNTIME_ART_METHOD_H_A


namespace art {

    union JValue;

    class OatQuickMethodHeader;

    class ProfilingInfo;

    class ScopedObjectAccessAlreadyRunnable;

    class StringPiece;

    class ShadowFrame;

    namespace mirror {
        class Array;

        class Class;

        class IfTable;

        class PointerArray;
        
        class ImtConflictTable {
            enum MethodIndex {
                kMethodInterface,
                kMethodImplementation,
                kMethodCount,  // Number of elements in enum.
            };

        private:
            union {
                uint32_t data32_[0];
                uint64_t data64_[0];
            };

        };

        class ArtMethod {
        public:
            uint32_t declaring_class_;
            uint32_t access_flags_;
            uint32_t dex_code_item_offset_;
            uint32_t dex_method_index_;
            uint16_t method_index_;
            uint16_t hotness_count_;
            struct PtrSizedFields {
                ArtMethod **dex_cache_resolved_methods_;
                uint32_t *dex_cache_resolved_types_;
                void *entry_point_from_jni_;
                void *entry_point_from_quick_compiled_code_;
            } ptr_sized_fields_;

        };

    }
} // namespace art

#endif  // ART_RUNTIME_ART_METHOD_H_A

我這里去掉了一些不需要的內(nèi)容逼庞,最重要的是要把ArtMethod結(jié)構(gòu)體中的參數(shù)列出來蛇更。

  1. 測試,在華為榮耀v9中可以。在內(nèi)置的android虛擬機中派任,debug模式下可以砸逊,正常運行后無法替換,比較奇怪掌逛,后續(xù)有發(fā)現(xiàn)原因师逸,再補充。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末豆混,一起剝皮案震驚了整個濱河市篓像,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌皿伺,老刑警劉巖员辩,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鸵鸥,居然都是意外死亡奠滑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門妒穴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宋税,“玉大人,你說我怎么就攤上這事讼油〗苋” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵汁讼,是天一觀的道長淆攻。 經(jīng)常有香客問我,道長嘿架,這世上最難降的妖魔是什么瓶珊? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮耸彪,結(jié)果婚禮上伞芹,老公的妹妹穿的比我還像新娘。我一直安慰自己蝉娜,他們只是感情好唱较,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著召川,像睡著了一般南缓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上荧呐,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天汉形,我揣著相機與錄音纸镊,去河邊找鬼。 笑死概疆,一個胖子當(dāng)著我的面吹牛逗威,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岔冀,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼凯旭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了使套?” 一聲冷哼從身側(cè)響起罐呼,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎童漩,沒想到半個月后弄贿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡矫膨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年差凹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侧馅。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡危尿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出馁痴,到底是詐尸還是另有隱情谊娇,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布罗晕,位于F島的核電站济欢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏小渊。R本人自食惡果不足惜法褥,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酬屉。 院中可真熱鬧半等,春花似錦、人聲如沸呐萨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谬擦。三九已至切距,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惨远,已是汗流浹背谜悟。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工饵沧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赌躺。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像羡儿,于是被迫代替她去往敵國和親礼患。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容