通过前面几节的讲解,我们已经基本了解了 class 文件的结构,每个字段代表什么含义,占多少字节,那么明确了 Class 文件的规则,接下来就可以读取 class 文件了,本节的代码均在项目的 classfile 包下。
Class 文件的结构
这里再次贴出 class 文件的结构描述:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
ClassFile { u4 magic; //魔数 u2 minor_version; //次版本号 u2 major_version; //主版本号 u2 constant_pool_count; //常量池大小 cp_info constant_pool[constant_pool_count-1]; //常量池 u2 access_flags; //类访问标志,表明 class 文件定义的是类还是接口,访问级别是 public 还是 private,等 u2 this_class; // u2 super_class; // u2 interfaces_count; //本类实现的接口数量 u2 interfaces[interfaces_count]; //实现的接口,存放在数组中 u2 fields_count; //本来中含有字段数 field_info fields[fields_count]; //数组中存放这各个字段 u2 methods_count; //本类中含有的方法数 method_info methods[methods_count]; //数组中存放着各个方法 u2 attributes_count; //本类中含有的属性数量; attribute_info attributes[attributes_count]; //数组中存放着各个属性 }
ClassFile 类
根据上面的 class 结构类型,我们自己定义的类 ClassFile 也呼之欲出,每个字段和上述 class 结构几乎是一样的。类中的一个成员变量定义如下
publicclassClassFile { int minorVersion; int majorVersion; ConstantPool constantPool; int accessFlags; int thisClass; int superClass; int[] interfaces; MemberInfo[] fields; MemberInfo[] methods; AttributeInfo[] attributes;
privatestatic ConstantInfo create(int tag, ConstantPool constantPool) { switch (tag) { case CONSTANT_Integer: returnnewConstantIntegerInfo(); case CONSTANT_Float: returnnewConstantFloatInfo(); case CONSTANT_Long: returnnewConstantLongInfo(); case CONSTANT_Double: returnnewConstantDoubleInfo(); case CONSTANT_Utf8: returnnewConstantUtf8Info(); case CONSTANT_String: returnnewConstantStringInfo(constantPool); case CONSTANT_Class: returnnewConstantClassInfo(constantPool); case CONSTANT_Fieldref: returnnewConstantMemberRefInfo(constantPool); case CONSTANT_Methodref: returnnewConstantMemberRefInfo(constantPool); case CONSTANT_InterfaceMethodref: returnnewConstantMemberRefInfo(constantPool); case CONSTANT_NameAndType: returnnewConstantNameAndTypeInfo(); // TODO: 2017/5/3 0003 下面三个类还未编码; case CONSTANT_MethodType: returnnewConstantMethodTypeInfo(); case CONSTANT_MethodHandle: returnnewConstantMethodHandleInfo(); case CONSTANT_InvokeDynamic: returnnewConstantInvokeDynamicInfo(); default: thrownewRuntimeException("java.lang.ClassFormatError: constant pool tag!"); } }