成员变量和成员方法的数据结构是一样的,所以可以使用相同的解析逻辑。首先解析出变量/方法的总数量,然后遍历并解析field_infomethod_info对象的所有信息。

    成员变量/成员方法解析代码片段:

    1. // u2 fields_count;
    2. this.fieldsCount = dis.readUnsignedShort();
    3. // field_info fields[fields_count];
    4. for (int i = 0; i < this.fieldsCount; i++) {
    5. // field_info {
    6. // u2 access_flags;
    7. // u2 name_index;
    8. // u2 descriptor_index;
    9. // u2 attributes_count;
    10. // attribute_info attributes[attributes_count];
    11. // }
    12. this.fieldList.add(readFieldOrMethod());
    13. }
    14. /**
    15. * 读取成员变量或者方法的公用属性
    16. *
    17. * @return 成员变量或方法属性信息
    18. * @throws IOException 读取异常
    19. */
    20. private Map<String, Object> readFieldOrMethod() throws IOException {
    21. Map<String, Object> dataMap = new LinkedHashMap<>();
    22. // u2 access_flags;
    23. dataMap.put("access", dis.readUnsignedShort());
    24. // u2 name_index;
    25. dataMap.put("name", getConstantPoolValue(dis.readUnsignedShort()));
    26. // u2 descriptor_index;
    27. dataMap.put("desc", getConstantPoolValue(dis.readUnsignedShort()));
    28. // u2 attributes_count;
    29. int attributesCount = dis.readUnsignedShort();
    30. dataMap.put("attributesCount", attributesCount);
    31. // 读取成员变量属性信息
    32. dataMap.put("attributes", readAttributes(attributesCount));
    33. return dataMap;
    34. }

    成员变量解析结果:

    1. {
    2. "fieldsCount": 4,
    3. "fieldList": [
    4. {
    5. "access": 2,
    6. "name": "password",
    7. "desc": "Ljava/lang/String;",
    8. "attributesCount": 0,
    9. "attributes": { }
    10. },
    11. {
    12. "access": 2,
    13. "name": "id",
    14. "desc": "J",
    15. "attributesCount": 0,
    16. "attributes": { }
    17. },
    18. {
    19. "access": 26,
    20. "name": "serialVersionUID",
    21. "desc": "J",
    22. "attributesCount": 1,
    23. "attributes": {
    24. "attributeName": "ConstantValue",
    25. "attributeLength": 2,
    26. "ConstantValue": {
    27. "constantValue": -7366591802115334000
    28. }
    29. }
    30. },
    31. {
    32. "access": 2,
    33. "name": "username",
    34. "desc": "Ljava/lang/String;",
    35. "attributesCount": 0,
    36. "attributes": { }
    37. }
    38. ]
    39. }

    成员方法解析结果(因结果过大,仅保留了一个getPassword方法):

    1. {
    2. "methodsCount": 10,
    3. "methodList": [
    4. {
    5. "access": 1,
    6. "name": "getPassword",
    7. "desc": "()Ljava/lang/String;",
    8. "attributesCount": 1,
    9. "attributes": {
    10. "attributeName": "Code",
    11. "attributeLength": 47,
    12. "Code": {
    13. "maxStack": 1,
    14. "maxLocals": 1,
    15. "codeLength": 5,
    16. "opcodes": [
    17. "aload_0",
    18. "getfield #15 <com/anbai/sec/bytecode/TestHelloWorld.password>",
    19. "areturn"
    20. ],
    21. "exceptionTable": {
    22. "exceptionTableLength": 0,
    23. "exceptionTableList": [ ]
    24. },
    25. "attributeLength": 47,
    26. "attributes": {
    27. "attributeName": "LocalVariableTable",
    28. "attributeLength": 12,
    29. "LineNumberTable": {
    30. "lineNumberTableLength": 1,
    31. "lineNumberTableList": [
    32. {
    33. "startPc": 0,
    34. "lineNumber": 49
    35. }
    36. ]
    37. },
    38. "LocalVariableTable": {
    39. "localVariableTableLength": 1,
    40. "localVariableTableList": [
    41. {
    42. "startPc": 0,
    43. "length": 5,
    44. "name": "this",
    45. "desc": "Lcom/anbai/sec/bytecode/TestHelloWorld;",
    46. "index": 0
    47. }
    48. ]
    49. }
    50. }
    51. }
    52. }
    53. }
    54. ]
    55. }