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.cybermkd.common.util.analysis.ParamNamesScaner Maven / Gradle / Ivy
package com.cybermkd.common.util.analysis;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.*;
/**
* Created by wangrenhui on 14/12/19.
*/
public class ParamNamesScaner {
/**
* 获取Method的形参名称列表
*
* @param method 需要解析的方法
* @return 形参名称列表, 如果没有调试信息, 将返回null
*/
public static ParamAttribute getParamNames(Method method) {
return getParamNames(method, getParamNames(method.getDeclaringClass()));
}
/**
* 获取Method的形参名称列表
*
* @param method 需要解析的方法
* @param classParamNames class所有的参数信息
* @return 形参名称列表, 如果没有调试信息, 将返回null
*/
public static ParamAttribute getParamNames(Method method, Map classParamNames) {
try {
ParamAttribute paramAttribute = classParamNames.get(getKey(method));
int size = method.getParameterTypes().length;
if (size == 0)
paramAttribute.setNames(new ArrayList(0));
else
paramAttribute.setNames(paramAttribute.getNames().subList(0, size));
return paramAttribute;
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 获取Constructor的形参名称列表
*
* @param constructor 需要解析的构造函数
* @return 形参名称列表, 如果没有调试信息, 将返回null
*/
public static ParamAttribute getParamNames(Constructor> constructor) {
return getParamNames(constructor, getParamNames(constructor.getDeclaringClass()));
}
/**
* 获取Constructor的形参名称列表
*
* @param constructor 需要解析的构造函数
* @param classParamNames class所有的参数信息
* @return 形参名称列表, 如果没有调试信息, 将返回null
*/
public static ParamAttribute getParamNames(Constructor> constructor, Map classParamNames) {
try {
ParamAttribute paramAttribute = classParamNames.get(getKey(constructor));
int size = constructor.getParameterTypes().length;
if (size == 0)
paramAttribute.setNames(new ArrayList(0));
else
paramAttribute.setNames(paramAttribute.getNames().subList(0, size));
return paramAttribute;
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
// ---------------------------------------------------------------------------------------------------
/**
* 获取一个类的所有方法/构造方法的形参名称Map
* 如果有任何IO异常,不应该有,如果是本地文件,那100%遇到bug了
*
* @param clazz 需要解析的类
* @return 所有方法/构造方法的形参名称Map
*/
public static Map getParamNames(Class> clazz) {
InputStream in = clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class");
try {
return getParamNames(in);
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static Map getParamNames(InputStream in)
throws IOException {
DataInputStream dis = new DataInputStream(new BufferedInputStream(in));
Map> names = new HashMap>();
Map lines = new HashMap();
Map strs = new HashMap();
dis.skipBytes(4);// Magic
dis.skipBytes(2);// 副版本号
dis.skipBytes(2);// 主版本号
// 读取常量池
int constant_pool_count = dis.readUnsignedShort();
for (int i = 0; i < (constant_pool_count - 1); i++) {
byte flag = dis.readByte();
switch (flag) {
case 7:// CONSTANT_Class:
dis.skipBytes(2);
break;
case 9:// CONSTANT_Fieldref:
case 10:// CONSTANT_Methodref:
case 11:// CONSTANT_InterfaceMethodref:
dis.skipBytes(2);
dis.skipBytes(2);
break;
case 8:// CONSTANT_String:
dis.skipBytes(2);
break;
case 3:// CONSTANT_Integer:
case 4:// CONSTANT_Float:
dis.skipBytes(4);
break;
case 5:// CONSTANT_Long:
case 6:// CONSTANT_Double:
dis.skipBytes(8);
i++;// 必须跳过一个,这是class文件设计的一个缺陷,历史遗留问题
break;
case 12:// CONSTANT_NameAndType:
dis.skipBytes(2);
dis.skipBytes(2);
break;
case 1:// CONSTANT_Utf8:
int len = dis.readUnsignedShort();
byte[] data = new byte[len];
dis.read(data);
strs.put(i + 1, new String(data, "UTF-8"));// 必然是UTF8的
break;
case 15:// CONSTANT_MethodHandle:
dis.skipBytes(1);
dis.skipBytes(2);
break;
case 16:// CONSTANT_MethodType:
dis.skipBytes(2);
break;
case 18:// CONSTANT_InvokeDynamic:
dis.skipBytes(2);
dis.skipBytes(2);
break;
default:
throw new RuntimeException("Impossible!! flag=" + flag);
}
}
dis.skipBytes(2);// 版本控制符
dis.skipBytes(2);// 类名
dis.skipBytes(2);// 超类
// 跳过接口定义
int interfaces_count = dis.readUnsignedShort();
dis.skipBytes(2 * interfaces_count);// 每个接口数据,是2个字节
// 跳过字段定义
int fields_count = dis.readUnsignedShort();
for (int i = 0; i < fields_count; i++) {
dis.skipBytes(2);
dis.skipBytes(2);
dis.skipBytes(2);
int attributes_count = dis.readUnsignedShort();
for (int j = 0; j < attributes_count; j++) {
dis.skipBytes(2);// 跳过访问控制符
int attribute_length = dis.readInt();
dis.skipBytes(attribute_length);
}
}
// 开始读取方法
int methods_count = dis.readUnsignedShort();
for (int i = 0; i < methods_count; i++) {
dis.skipBytes(2); // 跳过访问控制符
String methodName = strs.get(dis.readUnsignedShort());
String descriptor = strs.get(dis.readUnsignedShort());
short attributes_count = dis.readShort();
for (int j = 0; j < attributes_count; j++) {
String attrName = strs.get(dis.readUnsignedShort());
int attribute_length = dis.readInt();
if ("Code".equals(attrName)) { // 形参只在Code属性中
dis.skipBytes(2);
dis.skipBytes(2);
int code_len = dis.readInt();
dis.skipBytes(code_len); // 跳过具体代码
int exception_table_length = dis.readUnsignedShort();
dis.skipBytes(8 * exception_table_length); // 跳过异常表
int code_attributes_count = dis.readUnsignedShort();
for (int k = 0; k < code_attributes_count; k++) {
int str_index = dis.readUnsignedShort();
String codeAttrName = strs.get(str_index);
int code_attribute_length = dis.readInt();
if ("LocalVariableTable".equals(codeAttrName)) {// 形参在LocalVariableTable属性中
int local_variable_table_length = dis
.readUnsignedShort();
List varNames = new ArrayList(
local_variable_table_length);
for (int l = 0; l < local_variable_table_length; l++) {
dis.skipBytes(2);
dis.skipBytes(2);
String varName = strs.get(dis
.readUnsignedShort());
dis.skipBytes(2);
// index
int index = dis.readUnsignedShort();
if (!"this".equals(varName)) // 非静态方法,第一个参数是this
varNames.add(new LocalVariable(index,
varName));
}
names.put(methodName + "," + descriptor, varNames);
} else if ("LineNumberTable".equals(codeAttrName)) {
int n = dis.readUnsignedShort();
int[] lineNumberTable = new int[n];
for (int m = 0; m < n; m++) {
dis.readUnsignedShort(); // start_pc
lineNumberTable[m] = dis.readUnsignedShort(); // line_number
}
lines.put(methodName + "," + descriptor, lineNumberTable);
} else
dis.skipBytes(code_attribute_length);
}
} else
dis.skipBytes(attribute_length);
}
}
dis.close();
Set set = names.keySet();
Map reMap = new HashMap();
for (String key : set) {
LocalVariable[] tmpArr = names.get(key).toArray(
new LocalVariable[0]);
Arrays.sort(tmpArr);
List list = new ArrayList();
for (LocalVariable var : tmpArr) {
list.add(var.name);
}
reMap.put(key, new ParamAttribute(list, lines.get(key)));
}
return reMap;
}
/**
* 传入Method或Constructor,获取getParamNames方法返回的Map所对应的key
*/
public static String getKey(Object obj) {
StringBuilder sb = new StringBuilder();
if (obj instanceof Method) {
sb.append(((Method) obj).getName()).append(',');
getDescriptor(sb, (Method) obj);
} else if (obj instanceof Constructor) {
sb.append(","); // 只有非静态构造方法才能用有方法参数的,而且通过反射API拿不到静态构造方法
getDescriptor(sb, (Constructor>) obj);
} else
throw new RuntimeException("Not Method or Constructor!");
return sb.toString();
}
public static void getDescriptor(StringBuilder sb, Method method) {
sb.append('(');
for (Class> klass : method.getParameterTypes())
getDescriptor(sb, klass);
sb.append(')');
getDescriptor(sb, method.getReturnType());
}
public static void getDescriptor(StringBuilder sb,
Constructor> constructor) {
sb.append('(');
for (Class> klass : constructor.getParameterTypes())
getDescriptor(sb, klass);
sb.append(')');
sb.append('V');
}
/**
* 本方法来源于ow2的asm库的Type类
*/
public static void getDescriptor(final StringBuilder buf, final Class> c) {
Class> d = c;
while (true) {
if (d.isPrimitive()) {
char car;
if (d == Integer.TYPE) {
car = 'I';
} else if (d == Void.TYPE) {
car = 'V';
} else if (d == Boolean.TYPE) {
car = 'Z';
} else if (d == Byte.TYPE) {
car = 'B';
} else if (d == Character.TYPE) {
car = 'C';
} else if (d == Short.TYPE) {
car = 'S';
} else if (d == Double.TYPE) {
car = 'D';
} else if (d == Float.TYPE) {
car = 'F';
} else /* if (d == Long.TYPE) */ {
car = 'J';
}
buf.append(car);
return;
} else if (d.isArray()) {
buf.append('[');
d = d.getComponentType();
} else {
buf.append('L');
String name = d.getName();
int len = name.length();
for (int i = 0; i < len; ++i) {
char car = name.charAt(i);
buf.append(car == '.' ? '/' : car);
}
buf.append(';');
return;
}
}
}
static class LocalVariable implements Comparable {
public int index;
public String name;
public LocalVariable(int index, String name) {
this.index = index;
this.name = name;
}
public int compareTo(LocalVariable o) {
return this.index - o.index;
}
}
}