All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.adrninistrator.javacg2.util.JavaCG2ByteCodeUtil Maven / Gradle / Ivy
package com.adrninistrator.javacg2.util;
import com.adrninistrator.javacg2.common.JavaCG2CommonNameConstants;
import com.adrninistrator.javacg2.common.JavaCG2Constants;
import com.adrninistrator.javacg2.common.TypeConstants;
import com.adrninistrator.javacg2.common.enums.JavaCG2ConstantTypeEnum;
import com.adrninistrator.javacg2.dto.classes.InnerClassInfo;
import com.adrninistrator.javacg2.dto.method.MethodArgReturnTypes;
import org.apache.bcel.Const;
import org.apache.bcel.classfile.AccessFlags;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.InnerClass;
import org.apache.bcel.classfile.InnerClasses;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LineNumberTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Signature;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.generic.MethodGen;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author adrninistrator
* @date 2022/9/21
* @description:
*/
public class JavaCG2ByteCodeUtil {
private static final Logger logger = LoggerFactory.getLogger(JavaCG2ByteCodeUtil.class);
/**
* 判断当前方法是否为涉及继承的方法
*
* @param methodName
* @param accessFlags
* @return
*/
public static boolean checkExtendsMethod(String methodName, AccessFlags accessFlags) {
/*
同时满足以下条件:
非、
非静态
抽象方法,或public方法,或protected方法,或非public且非protected且非private方法
*/
return !methodName.startsWith("<")
&& !accessFlags.isStatic()
&& (accessFlags.isAbstract() || accessFlags.isPublic() || accessFlags.isProtected() || !accessFlags.isPrivate());
}
/**
* 判断当前方法是否为涉及实现的方法
*
* @param methodName
* @param accessFlags
* @return
*/
public static boolean checkImplMethod(String methodName, AccessFlags accessFlags) {
/*
同时满足以下条件:
非、
非静态
非抽象
public方法(只能为public,不能为默认修饰符)
*/
return !methodName.startsWith("<")
&& !accessFlags.isStatic()
&& !accessFlags.isAbstract()
&& accessFlags.isPublic();
}
/**
* 获取可能涉及继承的相关方法,包含参数
*
* @param methods
* @return
*/
public static Map genExtendsClassMethodWithArgTypes(Method[] methods) {
Map methodArgReturnTypesMap = new HashMap<>();
// 遍历类的方法
for (Method method : methods) {
String methodName = method.getName();
if (JavaCG2ByteCodeUtil.checkExtendsMethod(methodName, method)) {
// 对于可能涉及继承的方法进行记录
MethodArgReturnTypes methodArgReturnTypes = new MethodArgReturnTypes(methodName, method.getArgumentTypes(), method.getReturnType());
methodArgReturnTypesMap.put(methodArgReturnTypes, method.getAccessFlags());
}
}
return methodArgReturnTypesMap;
}
/**
* 获取可能涉及实现的相关方法,包含参数
*
* @param methods
* @return
*/
public static Map genImplClassMethodWithArgTypes(Method[] methods) {
Map methodInfoMap = new HashMap<>(methods.length);
for (Method method : methods) {
String methodName = method.getName();
if (checkImplMethod(methodName, method)) {
// 记录可能涉及实现的方法
methodInfoMap.put(new MethodArgReturnTypes(methodName, method.getArgumentTypes(), method.getReturnType()), method.getAccessFlags());
}
}
return methodInfoMap;
}
/**
* 获取接口相关的方法,包含参数
*
* @param methods
* @return
*/
public static Map genInterfaceMethodWithArgTypes(Method[] methods) {
Map methodInfoMap = new HashMap<>(methods.length);
for (Method method : methods) {
methodInfoMap.put(new MethodArgReturnTypes(method.getName(), method.getArgumentTypes(), method.getReturnType()), method.getAccessFlags());
}
return methodInfoMap;
}
/**
* 获取方法的起始代码行号
*
* @param method
* @return
*/
public static int getFuncStartSourceLine(Method method) {
LineNumberTable lineNumberTable = method.getLineNumberTable();
if (lineNumberTable == null || lineNumberTable.getLineNumberTable() == null) {
return JavaCG2Constants.DEFAULT_LINE_NUMBER;
}
return lineNumberTable.getLineNumberTable()[0].getLineNumber();
}
/**
* 获取构造函数的起始代码行号
*
* @param javaClass
* @return
*/
public static int getInitFuncStartSourceLine(JavaClass javaClass) {
Method[] methods = javaClass.getMethods();
if (methods == null) {
return JavaCG2Constants.DEFAULT_LINE_NUMBER;
}
for (Method method : methods) {
if (JavaCG2ClassMethodUtil.isInitMethod(method.getName())) {
return getFuncStartSourceLine(method);
}
}
return JavaCG2Constants.DEFAULT_LINE_NUMBER;
}
/**
* 去除类名中的数组形式
*
* @param className
* @return
*/
public static String removeArrayInClassName(String className) {
if (!className.startsWith("[")) {
return className;
}
// 处理数组格式
String tmpClassName = Utility.typeSignatureToString(className, false);
return removeArrayFlag(tmpClassName);
}
/**
* 获取对象对应的数组类型
*
* @param className
* @return
*/
public static String addArrayFlag(String className) {
return className + JavaCG2Constants.FLAG_ARRAY;
}
/**
* 去掉数组形式最后的[]
*
* @param arrayType
* @return
*/
public static String removeArrayFlag(String arrayType) {
if (arrayType == null) {
return null;
}
if (!isArrayType(arrayType) && !isNullType(arrayType)) {
logger.error("类名不是数组形式 {}", arrayType);
return arrayType;
}
return arrayType.substring(0, arrayType.length() - JavaCG2Constants.FLAG_ARRAY.length());
}
/**
* 去掉数组形式中全部的[]
*
* @param type
* @return
*/
public static String removeAllArrayFlag(String type) {
return StringUtils.replace(type, JavaCG2Constants.FLAG_ARRAY, "");
}
/**
* 判断是否为数组类型
*
* @param type
* @return
*/
public static boolean isArrayType(String type) {
return type.endsWith(JavaCG2Constants.FLAG_ARRAY);
}
/**
* 获取指定类型的长度
*
* @param typeString
* @return
*/
public static int getTypeSize(String typeString) {
if (JavaCG2ConstantTypeEnum.CONSTTE_DOUBLE.getType().equals(typeString) || JavaCG2ConstantTypeEnum.CONSTTE_LONG.getType().equals(typeString)) {
return 2;
}
return 1;
}
/**
* 判断是否为与int兼容的类型
*
* @param type
* @return false: 不类型 true: 类型
*/
public static boolean checkCompatibleWithInt(String type) {
for (String compatibleType : TypeConstants.COMPATIBLE_INT_TYPES) {
if (compatibleType.equals(type)) {
return true;
}
}
return false;
}
/**
* 判断类型是否为null
*
* @param type
* @return false: 不为null true: 为null
*/
public static boolean isNullType(String type) {
return type == null || JavaCG2ConstantTypeEnum.CONSTTE_NULL.getType().equals(type);
}
/**
* 比较两个类型是否兼容
*
* @param type1 不允许为null
* @param type2
* @return false: 不兼容 true: 兼容
*/
public static boolean compareType(String type1, String type2) {
if (type1.equals(type2)) {
return true;
}
if (compareIntType(type1, type2)) {
return true;
}
return compareByteBooleanType(type1, type2);
}
/**
* 比较指定的两个类型是否为与int兼容的类型
*
* @param type1
* @param type2
* @return false: 与int不兼容 true: 与int兼容
*/
public static boolean compareIntType(String type1, String type2) {
if (JavaCG2ConstantTypeEnum.CONSTTE_INT.getType().equals(type1) && checkCompatibleWithInt(type2)) {
return true;
}
return JavaCG2ConstantTypeEnum.CONSTTE_INT.getType().equals(type2) && checkCompatibleWithInt(type1);
}
/**
* 比较指定的两个类型是否为byte、boolean(或一维数组)兼容的类型
*
* @param type1
* @param type2
* @return false: 不兼容 true: 兼容
*/
public static boolean compareByteBooleanType(String type1, String type2) {
if (JavaCG2ConstantTypeEnum.CONSTTE_BYTE.getType().equals(type1) && JavaCG2ConstantTypeEnum.CONSTTE_BOOLEAN.getType().equals(type2)) {
return true;
}
if (JavaCG2ConstantTypeEnum.CONSTTE_BYTE.getType().equals(type2) && JavaCG2ConstantTypeEnum.CONSTTE_BOOLEAN.getType().equals(type1)) {
return true;
}
if (TypeConstants.BYTE_ARRAY_TYPE.equals(type1) && TypeConstants.BOOLEAN_ARRAY_TYPE.equals(type2)) {
return true;
}
return TypeConstants.BYTE_ARRAY_TYPE.equals(type2) && TypeConstants.BOOLEAN_ARRAY_TYPE.equals(type1);
}
/**
* 判断是否为public
*
* @param accessFlags
* @return
*/
public static boolean isPublicFlag(int accessFlags) {
return (accessFlags & Const.ACC_PUBLIC) != 0;
}
/**
* 判断是否为protected
*
* @param accessFlags
* @return
*/
public static boolean isProtectedMethod(int accessFlags) {
return (accessFlags & Const.ACC_PROTECTED) != 0;
}
/**
* 判断是否为private
*
* @param accessFlags
* @return
*/
public static boolean isPrivateMethod(int accessFlags) {
return (accessFlags & Const.ACC_PRIVATE) != 0;
}
/**
* 判断是否为abstract
*
* @param accessFlags
* @return
*/
public static boolean isAbstractFlag(int accessFlags) {
return (accessFlags & Const.ACC_ABSTRACT) != 0;
}
/**
* 判断是否为interface
*
* @param accessFlags
* @return
*/
public static boolean isInterfaceFlag(int accessFlags) {
return (accessFlags & Const.ACC_INTERFACE) != 0;
}
/**
* 判断是否有ACC_BRIDGE标志
*
* @param accessFlags
* @return
*/
public static boolean isBridgeFlag(int accessFlags) {
return (accessFlags & Const.ACC_BRIDGE) != 0;
}
/**
* 判断是否为Enum
*
* @param accessFlags
* @return
*/
public static boolean isEnumFlag(int accessFlags) {
return (accessFlags & Const.ACC_ENUM) != 0;
}
/**
* 设置public标志
*
* @param accessFlags
* @param trueOrFalse
* @return
*/
public static int setPublicFlag(int accessFlags, boolean trueOrFalse) {
return setFlag(accessFlags, Const.ACC_PUBLIC, trueOrFalse);
}
/**
* 设置protected标志
*
* @param accessFlags
* @param trueOrFalse
* @return
*/
public static int setProtectedFlag(int accessFlags, boolean trueOrFalse) {
return setFlag(accessFlags, Const.ACC_PROTECTED, trueOrFalse);
}
/**
* 设置public标志
*
* @param accessFlags
* @param trueOrFalse
* @return
*/
public static int setAbstractFlag(int accessFlags, boolean trueOrFalse) {
return setFlag(accessFlags, Const.ACC_ABSTRACT, trueOrFalse);
}
/**
* 设置指定位的标记
*
* @param accessFlags
* @param flag
* @param trueOrFalse
* @return
*/
private static int setFlag(int accessFlags, int flag, boolean trueOrFalse) {
if ((accessFlags & flag) != 0) { // Flag is set already
if (!trueOrFalse) {
accessFlags ^= flag;
}
} else if (trueOrFalse) {
accessFlags |= flag;
}
return accessFlags;
}
/**
* 获得修饰符字符串
*
* @param accessFlags
* @return
*/
public static String getModifiersString(int accessFlags) {
if (isPublicFlag(accessFlags)) {
return JavaCG2CommonNameConstants.MODIFIERS_PUBLIC;
}
if (isProtectedMethod(accessFlags)) {
return JavaCG2CommonNameConstants.MODIFIERS_PROTECTED;
}
if (isPrivateMethod(accessFlags)) {
return JavaCG2CommonNameConstants.MODIFIERS_PRIVATE;
}
return JavaCG2CommonNameConstants.MODIFIERS_DEFAULT;
}
/**
* 获取类的Signature
*
* @param javaClass
* @return
*/
public static Signature getSignatureOfClass(JavaClass javaClass) {
for (Attribute attribute : javaClass.getAttributes()) {
if (attribute instanceof Signature) {
return (Signature) attribute;
}
}
return null;
}
/**
* 判断指定的类是否为匿名内部类
*
* @param javaClass
* @return
*/
public static boolean checkInnerAnonymousClass(JavaClass javaClass) {
// 根据类名判断是否为匿名内部类
if (!JavaCG2ClassMethodUtil.isInnerAnonymousClass(javaClass.getClassName())) {
return false;
}
for (Attribute attribute : javaClass.getAttributes()) {
if (!(attribute instanceof InnerClasses)) {
continue;
}
InnerClasses innerClasses = (InnerClasses) attribute;
for (InnerClass innerClass : innerClasses.getInnerClasses()) {
int innerClassIndex = innerClass.getInnerClassIndex();
if (innerClassIndex == javaClass.getClassNameIndex()) {
// 当前类是内部类
return true;
}
}
}
return false;
}
/**
* 获取类中的内部类信息
*
* @param javaClass
* @return
*/
public static List getInnerClassInfo(JavaClass javaClass) {
List innerClassInfoList = new ArrayList<>(0);
String className = javaClass.getClassName();
ConstantPool constantPool = javaClass.getConstantPool();
for (Attribute attribute : javaClass.getAttributes()) {
if (!(attribute instanceof InnerClasses)) {
continue;
}
InnerClasses innerClasses = (InnerClasses) attribute;
for (InnerClass innerClass : innerClasses.getInnerClasses()) {
int innerClassIndex = innerClass.getInnerClassIndex();
if (innerClassIndex == javaClass.getClassNameIndex()) {
// 当前类是内部类,跳过
continue;
}
String innerClassName = constantPool.getConstantString(innerClassIndex, Const.CONSTANT_Class);
innerClassName = Utility.compactClassName(innerClassName, false);
if (JavaCG2ClassMethodUtil.isClassInJdk(innerClassName) ||
!innerClassName.startsWith(className) ||
StringUtils.countMatches(innerClassName, '$') < StringUtils.countMatches(className, '$')) {
/*
JDK中的类,跳过
当前内部类不是当前类的内部类,跳过
当前类是当前内部类对应的外部类,跳过
*/
continue;
}
InnerClassInfo innerClassInfo = new InnerClassInfo(innerClassName, className, JavaCG2ClassMethodUtil.isInnerAnonymousClass(innerClassName));
innerClassInfoList.add(innerClassInfo);
}
}
return innerClassInfoList;
}
/**
* 获取指定的变量下标在当前方法中的参数下标
*
* @param mg
* @param variableIndex 变量下标
* @return -1: 不是获取方法参数 >=0: 方法参数下标(从0开始)
*/
public static int getArgIndexInMethod(MethodGen mg, int variableIndex) {
int argIndex = variableIndex - (mg.isStatic() ? 0 : 1);
return argIndex < mg.getArgumentTypes().length ? argIndex : -1;
}
/**
* 获取指定的方法参数在LocalVariableTable中的下标
*
* @param mg
* @param argIndex
* @return
*/
public static int getLocalVariableTableIndex(MethodGen mg, int argIndex) {
return argIndex + (mg.isStatic() ? 0 : 1);
}
private JavaCG2ByteCodeUtil() {
throw new IllegalStateException("illegal");
}
}