All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.flyjingfish.android_aop_plugin.scanner_visitor.MethodReplaceInvokeAdapter.kt Maven / Gradle / Ivy

Go to download

Lightweight Aop for Android platform, you deserve it, action is worse than your heartbeat

There is a newer version: 2.2.8
Show newest version
package com.flyjingfish.android_aop_plugin.scanner_visitor

import com.flyjingfish.android_aop_plugin.beans.ReplaceMethodInfo
import com.flyjingfish.android_aop_plugin.utils.InitConfig
import com.flyjingfish.android_aop_plugin.utils.Utils
import com.flyjingfish.android_aop_plugin.utils.WovenInfoUtils
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes


class MethodReplaceInvokeAdapter(private val className:String,private val superName: String,
                                 private val methodName:String,private val methodDesc:String, methodVisitor: MethodVisitor?) :
    MethodVisitor(Opcodes.ASM9, methodVisitor) {
    private val methodNameDesc = Utils.getRealMethodName(methodName)+methodDesc
    private val isConstructorMethod = methodNameDesc.startsWith("(")
    private val canReplaceMethod = !(superName == "kotlin/coroutines/jvm/internal/ContinuationImpl" && methodNameDesc == "invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;" )

    interface OnResultListener{
        fun onBack()
    }
    var onResultListener : OnResultListener ?= null


    override fun visitTypeInsn(opcode: Int, type: String) {
        if (opcode == Opcodes.NEW) {
            val replaceMethodInfo = getReplaceInfo(type, "", "")
            if (replaceMethodInfo != null && replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW && replaceMethodInfo.newClassName.isNotEmpty()){
                super.visitTypeInsn(opcode, replaceMethodInfo.newClassName)
                return
            }
        }
        super.visitTypeInsn(opcode, type)
    }

    private fun getReplaceInfo(owner: String,
                        name: String,
                        descriptor: String):ReplaceMethodInfo?{
        val key = owner + name + descriptor
        var replaceMethodInfo = WovenInfoUtils.getReplaceMethodInfoUse(key)
        var isReplaceClass = false
        if (replaceMethodInfo == null){
            val oldOwner = WovenInfoUtils.getRealReplaceInfo(owner)
            if (oldOwner != null){
                val oldKey = oldOwner + name + descriptor
                replaceMethodInfo = WovenInfoUtils.getReplaceMethodInfoUse(oldKey)
                isReplaceClass = replaceMethodInfo != null && replaceMethodInfo.oldOwner == oldOwner && replaceMethodInfo.oldMethodName == name && replaceMethodInfo.oldMethodDesc == descriptor
            }
        }else{
            isReplaceClass = replaceMethodInfo.oldOwner == owner && replaceMethodInfo.oldMethodName == name && replaceMethodInfo.oldMethodDesc == descriptor
        }
        return if (isReplaceClass){
            replaceMethodInfo
        }else {
            null
        }
    }

    override fun visitMethodInsn(
        opcode: Int,
        owner: String,
        name: String,
        descriptor: String,
        isInterface: Boolean
    ) {
        var replaceMethodInfo = getReplaceInfo(owner, name, "")
        var isReplaceClass = replaceMethodInfo != null && replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW && replaceMethodInfo.newClassName.isNotEmpty()
        if (!isReplaceClass){
            val methodReplaceMethodInfo = getReplaceInfo(owner, name, descriptor)
            if (methodReplaceMethodInfo != null){
                replaceMethodInfo = methodReplaceMethodInfo
            }
            isReplaceClass = replaceMethodInfo != null
        }

        if (isReplaceClass && replaceMethodInfo != null
            && (!className.contains(replaceMethodInfo.newOwner) || methodNameDesc != "${replaceMethodInfo.newMethodName}${replaceMethodInfo.newMethodDesc}")) {
            val shouldReplace: Boolean = if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW){
                if (isConstructorMethod){
                    !(owner == superName && name == "")
                }else{
                    "" == replaceMethodInfo.oldMethodDesc
                }
            }else if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.INIT) {
                if (isConstructorMethod){
                    !(owner == superName && name == "")
                }else{
                    descriptor == replaceMethodInfo.oldMethodDesc
                }
            } else if (opcode == Opcodes.INVOKESTATIC) {
                descriptor == replaceMethodInfo.newMethodDesc
            } else {
                descriptor.replace("(", "(L${replaceMethodInfo.oldOwner};") == replaceMethodInfo.newMethodDesc || descriptor.replace("(", "(Ljava/lang/Object;") == replaceMethodInfo.newMethodDesc
            }
            if (shouldReplace) {
                if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW && replaceMethodInfo.isCallNew()) {
                    super.visitMethodInsn(opcode, replaceMethodInfo.newClassName, name, descriptor, isInterface)
                }else if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.INIT) {
                    super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
                }
                InitConfig.addReplaceMethodInfo(replaceMethodInfo)
                if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW && !replaceMethodInfo.isCallNew()){
                    super.visitMethodInsn(opcode, replaceMethodInfo.newClassName, name, descriptor, isInterface)
                }else{
                    if (canReplaceMethod){
                        // 注意,最后一个参数是false,会不会太武断呢?
                        super.visitMethodInsn(
                            Opcodes.INVOKESTATIC,
                            replaceMethodInfo.newOwner,
                            replaceMethodInfo.newMethodName,
                            replaceMethodInfo.newMethodDesc,
                            false
                        )
                        onResultListener?.onBack()
                    }else {
                        super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
                    }
                }
            } else {
                super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
            }
        } else {
            super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy