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

com.adrninistrator.javacg2.util.JavaCG2BootstrapMethodUtil Maven / Gradle / Ivy

package com.adrninistrator.javacg2.util;

import com.adrninistrator.javacg2.dto.method.JavaCG2MethodInfo;
import org.apache.bcel.Const;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.BootstrapMethod;
import org.apache.bcel.classfile.BootstrapMethods;
import org.apache.bcel.classfile.ClassFormatException;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantCP;
import org.apache.bcel.classfile.ConstantFieldref;
import org.apache.bcel.classfile.ConstantMethodHandle;
import org.apache.bcel.classfile.ConstantNameAndType;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.generic.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author adrninistrator
 * @date 2022/10/7
 * @description:
 */
public class JavaCG2BootstrapMethodUtil {
    private static final Logger logger = LoggerFactory.getLogger(JavaCG2BootstrapMethodUtil.class);

    /**
     * 获得JavaClass中指定下标的BootstrapMethod
     *
     * @param javaClass
     * @param index
     * @return
     */
    public static BootstrapMethod getBootstrapMethod(JavaClass javaClass, int index) {
        for (Attribute attribute : javaClass.getAttributes()) {
            if (attribute instanceof BootstrapMethods) {
                BootstrapMethods bootstrapMethods = (BootstrapMethods) attribute;
                BootstrapMethod[] bootstrapMethodArray = bootstrapMethods.getBootstrapMethods();
                if (bootstrapMethodArray != null && bootstrapMethodArray.length > index) {
                    return bootstrapMethodArray[index];
                }
            }
        }
        return null;
    }

    /**
     * 获得BootstrapMethod的方法信息
     *
     * @param bootstrapMethod
     * @param javaClass
     * @return
     */
    public static JavaCG2MethodInfo getBootstrapMethodInfo(BootstrapMethod bootstrapMethod, JavaClass javaClass) {
        for (int argIndex : bootstrapMethod.getBootstrapArguments()) {
            Constant constantArg = javaClass.getConstantPool().getConstant(argIndex);
            if (!(constantArg instanceof ConstantMethodHandle)) {
                continue;
            }

            JavaCG2MethodInfo javaCG2MethodInfo = getMethodFromConstantMethodHandle((ConstantMethodHandle) constantArg, javaClass);
            if (javaCG2MethodInfo != null) {
                return javaCG2MethodInfo;
            }
        }

        return null;
    }

    /**
     * 根据ConstantMethodHandle获得Method对象
     *
     * @param constantMethodHandle
     * @param javaClass
     * @return
     */
    public static JavaCG2MethodInfo getMethodFromConstantMethodHandle(ConstantMethodHandle constantMethodHandle, JavaClass javaClass) {
        ConstantPool constantPool = javaClass.getConstantPool();

        Constant constantCP = constantPool.getConstant(constantMethodHandle.getReferenceIndex());
        if (!(constantCP instanceof ConstantCP)) {
            logger.error("不满足instanceof ConstantCP {}", constantCP.getClass().getName());
            return null;
        }

        if (constantCP instanceof ConstantFieldref) {
            return null;
        }
        ConstantCP constantClassAndMethod = (ConstantCP) constantCP;
        String className = constantPool.getConstantString(constantClassAndMethod.getClassIndex(), Const.CONSTANT_Class);
        className = Utility.compactClassName(className, false);

        Constant constantNAT = constantPool.getConstant(constantClassAndMethod.getNameAndTypeIndex());
        if (!(constantNAT instanceof ConstantNameAndType)) {
            logger.error("不满足instanceof ConstantNameAndType {}", constantNAT.getClass().getName());
            return null;
        }
        ConstantNameAndType constantNameAndType = (ConstantNameAndType) constantNAT;
        String methodName = constantPool.constantToString(constantNameAndType.getNameIndex(), Const.CONSTANT_Utf8);
        String methodArgsReturn = constantPool.constantToString(constantNameAndType.getSignatureIndex(), Const.CONSTANT_Utf8);
        if (methodName != null && methodArgsReturn != null) {
            try {
                Type[] methodArgTypes = Type.getArgumentTypes(methodArgsReturn);
                Type returnType = Type.getReturnType(methodArgsReturn);
                return new JavaCG2MethodInfo(className, methodName, methodArgTypes, returnType);
            } catch (ClassFormatException e) {
                logger.error("方法参数与返回类型不符合预期,不处理 {} {}", methodArgsReturn, constantClassAndMethod.getClass().getName());
                return null;
            }
        }

        logger.error("获取方法信息失败 {} {} {} {}", javaClass.getClassName(), className, methodName, methodArgsReturn);
        return null;
    }

    private JavaCG2BootstrapMethodUtil() {
        throw new IllegalStateException("illegal");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy