最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android開發(fā)AsmClassVisitorFactory使用詳解

 更新時間:2022年06月21日 17:27:13   作者:究極逮蝦戶  
這篇文章主要為大家介紹了Android開發(fā)AsmClassVisitorFactory使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

之前就和大家介紹過AGP(Android Gradle Plugin) 7.0.0版本之后Transform 已經(jīng)過期即將廢棄的事情。而且也簡單的介紹了替換的方式是Transform Action,經(jīng)過我這一陣子的學習和調(diào)研,發(fā)現(xiàn)只能說答對了一半吧。下面介紹個新東西AsmClassVisitorFactory。

com.android.build.api.instrumentation.AsmClassVisitorFactory

A factory to create class visitor objects to instrument classes.

The implementation of this interface must be an abstract class where the parameters and instrumentationContext are left unimplemented. The class must have an empty constructor which will be used to construct the factory object.

當前官方推薦使用的應(yīng)該是這個類,這個類的底層實現(xiàn)就是基于gradle原生的Transform Action,這次的學習過程其實走了一點點彎路,一開始嘗試的是Transform Action,但是貌似彎彎繞繞的,最后也沒有成功,而且Transform Action的輸入產(chǎn)物都是單一文件,修改也是針對單一文件的,所以貌似也不完全是一個很好的替換方案,之前文章介紹的那種復(fù)雜的asm操作則無法負荷了。

AsmClassVisitorFactory根據(jù)官方說法,編譯速度會有提升,大概18%左右,這個下面我們會在使用階段對其進行介紹的。

我們先從AsmClassVisitorFactory這個抽象接口開始介紹起吧。

AsmClassVisitorFactory

@Incubating
interface AsmClassVisitorFactory<ParametersT : InstrumentationParameters> : Serializable {
    /**
     * The parameters that will be instantiated, configured using the given config when registering
     * the visitor, and injected on instantiation.
     *
     * This field must be left unimplemented.
     */
    @get:Nested
    val parameters: Property<ParametersT>
    /**
     * Contains parameters to help instantiate the visitor objects.
     *
     * This field must be left unimplemented.
     */
    @get:Nested
    val instrumentationContext: InstrumentationContext
    /**
     * Creates a class visitor object that will visit a class with the given [classContext]. The
     * returned class visitor must delegate its calls to [nextClassVisitor].
     *
     * The given [classContext] contains static information about the classes before starting the
     * instrumentation process. Any changes in interfaces or superclasses for the class with the
     * given [classContext] or for any other class in its classpath by a previous visitor will
     * not be reflected in the [classContext] object.
     *
     * [classContext] can also be used to get the data for classes that are in the runtime classpath
     * of the class being visited.
     *
     * This method must handle asynchronous calls.
     *
     * @param classContext contains information about the class that will be instrumented by the
     *                     returned class visitor.
     * @param nextClassVisitor the [ClassVisitor] to which the created [ClassVisitor] must delegate
     *                         method calls.
     */
    fun createClassVisitor(
        classContext: ClassContext,
        nextClassVisitor: ClassVisitor
    ): ClassVisitor
    /**
     * Whether or not the factory wants to instrument the class with the given [classData].
     *
     * If returned true, [createClassVisitor] will be called and the returned class visitor will
     * visit the class.
     *
     * This method must handle asynchronous calls.
     */
    fun isInstrumentable(classData: ClassData): Boolean
}

簡單的分析下這個接口,我們要做的就是在createClassVisitor這個方法中返回一個ClassVisitor,正常我們在構(gòu)造ClassVisitor實例的時候是需要傳入下一個ClassVisitor實例的,所以我們之后在new的時候傳入nextClassVisitor就行了。

另外就是isInstrumentable,這個方法是判斷當前類是否要進行掃描,因為如果所有類都要通過ClassVisitor進行掃描還是太耗時了,我們可以通過這個方法過濾掉很多我們不需要掃描的類。

@Incubating
interface ClassData {
    /**
     * Fully qualified name of the class.
     */
    val className: String
    /**
     * List of the annotations the class has.
     */
    val classAnnotations: List<String>
    /**
     * List of all the interfaces that this class or a superclass of this class implements.
     */
    val interfaces: List<String>
    /**
     * List of all the super classes that this class or a super class of this class extends.
     */
    val superClasses: List<String>
}

ClassData并不是asm的api,所以其中包含的內(nèi)容相對來說比較少,但是應(yīng)該也勉強夠用了。這部分大家簡單看看就行了,就不多做介紹了呢。

新的Extension

AGP版本升級之后,應(yīng)該是為了區(qū)分新舊版的Extension,所以在AppExtension的基礎(chǔ)上,新增了一個AndroidComponentsExtension出來。

我們的transformClassesWith就需要注冊在這個上面。這個需要考慮到變種,和之前的Transform還是有比較大的區(qū)別的,這樣我們就可以基于不同的變種增加對應(yīng)的適配工作了。

        val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
        androidComponents.onVariants { variant ->
            variant.transformClassesWith(PrivacyClassVisitorFactory::class.java,
                    InstrumentationScope.ALL) {}
            variant.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
        }

實戰(zhàn)

這次還是在之前的敏感權(quán)限api替換的字節(jié)碼替換工具的基礎(chǔ)上進行測試開發(fā)。

ClassVisitor

看看我們正常是如何寫一個簡單的ClassVisitor的。

ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor methodFilterCV = new ClassFilterVisitor(classWriter);
ClassReader cr = new ClassReader(srcClass);
cr.accept(methodFilterCV, ClassReader.SKIP_DEBUG);
return classWriter.toByteArray();

首先我們會構(gòu)造好一個空的ClassWriter,接著會構(gòu)造一個ClassVisitor實例,然后傳入這個ClassWriter。然后我們構(gòu)造一個ClassReader實例,然后將byte數(shù)組傳入,之后調(diào)用classReader.accept方法,之后我們就能在visitor中逐個訪問數(shù)據(jù)了。

那么其實我們的類信息,方法啥的都是通過ClassReader讀入的,然后由當前的ClassVisitor訪問完之后交給我們最后一個ClassWriter

其中ClassWriter也是一個ClassVisitor對象,他復(fù)雜重新將修改過的類轉(zhuǎn)化成byte數(shù)據(jù)??梢钥吹贸鰜?code>ClassVisitor就有一個非常簡單的鏈表結(jié)構(gòu),之后逐層向下訪問。

介紹完了這個哦,我們做個大膽的假設(shè),如果我們這個ClassVisitor鏈表前插入幾個不同的ClassVisitor,那么我們是不是就可以讓asm修改逐個生效,然后也不需要多余的io操作了呢。這就是新的asm api 的設(shè)計思路了,也是我們這邊大佬的字節(jié)碼框架大佬的設(shè)計。另外bytex內(nèi)的設(shè)計思路也是如此。

tips ClassNode 因為是先生成的語法樹,所以和一般的ClassVisitor有點小區(qū)別,需要在visitEnd方法內(nèi)調(diào)用accept(next)

實際代碼分析

接下來我們上實戰(zhàn)咯。我將之前的代碼套用到這次的邏輯上來。

demo地址

abstract class PrivacyClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
    override fun createClassVisitor(classContext: ClassContext, nextClassVisitor: ClassVisitor): ClassVisitor {
        return PrivacyClassNode(nextClassVisitor)
    }
    override fun isInstrumentable(classData: ClassData): Boolean {
        return true
    }
}

我在isInstrumentable都返回的是true,其實我可以將掃描規(guī)則限定在特定包名內(nèi),這樣就可以加快構(gòu)建速度了。

class PrivacyClassNode(private val nextVisitor: ClassVisitor) : ClassNode(Opcodes.ASM5) {
    override fun visitEnd() {
        super.visitEnd()
        PrivacyHelper.whiteList.let {
            val result = it.firstOrNull { whiteName ->
                name.contains(whiteName, true)
            }
            result
        }.apply {
            if (this == null) {
                //   println("filter: $name")
            }
        }
        PrivacyHelper.whiteList.firstOrNull {
            name.contains(it, true)
        }?.apply {
            val iterator: Iterator<MethodNode> = methods.iterator()
            while (iterator.hasNext()) {
                val method = iterator.next()
                method.instructions?.iterator()?.forEach {
                    if (it is MethodInsnNode) {
                        it.isPrivacy()?.apply {
                            println("privacy transform classNodeName: ${name@this}")
                            it.opcode = code
                            it.owner = owner
                            it.name = name
                            it.desc = desc
                        }
                    }
                }
            }
        }
        accept(nextVisitor)
    }
}
private fun MethodInsnNode.isPrivacy(): PrivacyAsmEntity? {
    val pair = PrivacyHelper.privacyList.firstOrNull {
        val first = it.first
        first.owner == owner && first.code == opcode && first.name == name && first.desc == desc
    }
    return pair?.second
}

這部分比較簡單,把邏輯抽象定義在類ClassNode內(nèi),然后在visitEnd方法的時候調(diào)用我之前說的accept(nextVisitor)方法。

另外就是注冊邏輯了,和我前面介紹的內(nèi)容基本都是一樣的。

個人觀點

AsmClassVisitorFactory相比較于之前的Transform確實簡化了非常非常多,我們不需要關(guān)心之前的增量更新等等邏輯,只要專注于asm api的操作就行了。

其次就是因為減少了io操作,所以其速度自然也就比之前有所提升。同時因為基于的是Transform Action,所以整體性能還是非常ok的,那部分增量可以說是更簡單了。

另外我也和我的同事大佬交流過哦,復(fù)雜的這種類似上篇文章介紹的,最好還是使用Gradle Task的形式進行修改。

以上就是Android開發(fā)AsmClassVisitorFactory使用詳解的詳細內(nèi)容,更多關(guān)于Android開發(fā)AsmClassVisitorFactory的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android隱藏手機底部虛擬按鍵的方法

    Android隱藏手機底部虛擬按鍵的方法

    這篇文章主要為大家詳細介紹了Android隱藏手機底部虛擬按鍵的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Android組件之服務(wù)的詳解

    Android組件之服務(wù)的詳解

    這篇文章主要詳細介紹了Android組件之一的服務(wù),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • Android MessageQueue消息隊列主要作用詳解

    Android MessageQueue消息隊列主要作用詳解

    Android 消息機制主要指的是 Handler 的運行機制及其所依賴的 MessageQueue 和 Looper 的工作過程,Handler、MessageQueue、Looper組成一個相互聯(lián)系的整體。本文先從 MessageQueue 的源碼來說明其實現(xiàn)原理
    2023-02-02
  • Android異步上傳圖片到PHP服務(wù)器

    Android異步上傳圖片到PHP服務(wù)器

    這篇文章主要介紹了Android異步上傳圖片到PHP服務(wù)器的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • Android權(quán)限機制深入分析講解

    Android權(quán)限機制深入分析講解

    Android的權(quán)限管理遵循的是“最小特權(quán)原則”,即所有的Android應(yīng)用程序都被賦予了最小權(quán)限。一個Android應(yīng)用程序如果沒有聲明任何權(quán)限,就沒有任何特權(quán)
    2022-12-12
  • Android中深入學習對象的四種引用類型

    Android中深入學習對象的四種引用類型

    這篇文章主要介紹Android中深入學習對象的四種引用類型,Java中,一切被視為對象,引用則是用來操縱對象的;在JDK1.2就把對象引用分為四種級別,從而使程序能更靈活控制它的生命周期,級別由高到底依次為強引用、軟引用、弱引用、虛引用,需要的朋友可以參考一下
    2021-10-10
  • Android改變手機屏幕朝向的方法

    Android改變手機屏幕朝向的方法

    這篇文章主要介紹了Android改變手機屏幕朝向的方法,涉及Android動態(tài)更改手機屏幕朝向的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • Android入門教程之組件Activity的生命周期詳解

    Android入門教程之組件Activity的生命周期詳解

    Activity作為四大組件之一,出現(xiàn)的頻率相當高,基本上我們在android的各個地方都能看見它的蹤影,因此深入了解Activity,對于開發(fā)高質(zhì)量應(yīng)用程序是很有幫助的。今天我們就來詳細地聊聊Activity的生命周期,以便我們在以后的開發(fā)中能如魚得水
    2021-10-10
  • Android實現(xiàn)圖片裁剪和上傳

    Android實現(xiàn)圖片裁剪和上傳

    這篇文章主要為大家詳細介紹了Android實現(xiàn)圖片的裁剪和上傳,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • AFURLSessionManager 上傳下載使用代碼說明

    AFURLSessionManager 上傳下載使用代碼說明

    本文通過代碼給大家介紹了AFURLSessionManager 上傳下載使用說明,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-09-09

最新評論

黄梅县| 定安县| 河津市| 米林县| 酉阳| 长顺县| 互助| 哈巴河县| 南澳县| 湛江市| 手游| 剑河县| 乳山市| 孟连| 公安县| 满城县| 彭州市| 慈溪市| 桃园县| 建始县| 无锡市| 博兴县| 广河县| 宁陕县| 五常市| 仪征市| 福清市| 滨州市| 青阳县| 滁州市| 洛阳市| 黄浦区| 汪清县| 长岭县| 武安市| 葵青区| 县级市| 苍梧县| 凤城市| 阿拉善左旗| 哈尔滨市|