成员变量和成员方法的数据结构是一样的,所以可以使用相同的解析逻辑。首先解析出变量/方法的总数量,然后遍历并解析field_info
或method_info
对象的所有信息。
成员变量/成员方法解析代码片段:
// u2 fields_count;
this.fieldsCount = dis.readUnsignedShort();
// field_info fields[fields_count];
for (int i = 0; i < this.fieldsCount; i++) {
// field_info {
// u2 access_flags;
// u2 name_index;
// u2 descriptor_index;
// u2 attributes_count;
// attribute_info attributes[attributes_count];
// }
this.fieldList.add(readFieldOrMethod());
}
/**
* 读取成员变量或者方法的公用属性
*
* @return 成员变量或方法属性信息
* @throws IOException 读取异常
*/
private Map<String, Object> readFieldOrMethod() throws IOException {
Map<String, Object> dataMap = new LinkedHashMap<>();
// u2 access_flags;
dataMap.put("access", dis.readUnsignedShort());
// u2 name_index;
dataMap.put("name", getConstantPoolValue(dis.readUnsignedShort()));
// u2 descriptor_index;
dataMap.put("desc", getConstantPoolValue(dis.readUnsignedShort()));
// u2 attributes_count;
int attributesCount = dis.readUnsignedShort();
dataMap.put("attributesCount", attributesCount);
// 读取成员变量属性信息
dataMap.put("attributes", readAttributes(attributesCount));
return dataMap;
}
成员变量解析结果:
{
"fieldsCount": 4,
"fieldList": [
{
"access": 2,
"name": "password",
"desc": "Ljava/lang/String;",
"attributesCount": 0,
"attributes": { }
},
{
"access": 2,
"name": "id",
"desc": "J",
"attributesCount": 0,
"attributes": { }
},
{
"access": 26,
"name": "serialVersionUID",
"desc": "J",
"attributesCount": 1,
"attributes": {
"attributeName": "ConstantValue",
"attributeLength": 2,
"ConstantValue": {
"constantValue": -7366591802115334000
}
}
},
{
"access": 2,
"name": "username",
"desc": "Ljava/lang/String;",
"attributesCount": 0,
"attributes": { }
}
]
}
成员方法解析结果(因结果过大,仅保留了一个getPassword
方法):
{
"methodsCount": 10,
"methodList": [
{
"access": 1,
"name": "getPassword",
"desc": "()Ljava/lang/String;",
"attributesCount": 1,
"attributes": {
"attributeName": "Code",
"attributeLength": 47,
"Code": {
"maxStack": 1,
"maxLocals": 1,
"codeLength": 5,
"opcodes": [
"aload_0",
"getfield #15 <com/anbai/sec/bytecode/TestHelloWorld.password>",
"areturn"
],
"exceptionTable": {
"exceptionTableLength": 0,
"exceptionTableList": [ ]
},
"attributeLength": 47,
"attributes": {
"attributeName": "LocalVariableTable",
"attributeLength": 12,
"LineNumberTable": {
"lineNumberTableLength": 1,
"lineNumberTableList": [
{
"startPc": 0,
"lineNumber": 49
}
]
},
"LocalVariableTable": {
"localVariableTableLength": 1,
"localVariableTableList": [
{
"startPc": 0,
"length": 5,
"name": "this",
"desc": "Lcom/anbai/sec/bytecode/TestHelloWorld;",
"index": 0
}
]
}
}
}
}
}
]
}