马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1 准备工作
获取class文件byte[]- public static byte[] getFileBytes(File file) {
- try (FileInputStream fileInputStream = new FileInputStream(file)) {
- int available = fileInputStream.available();
- byte[] data=new byte[available];
- fileInputStream.read(data,0,available-1);
- return data;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
复制代码 这里使用jdk的ByteBuffer包装bytes
ByteBuffer data = ByteBuffer.wrap(getFileBytes(file));
因为ByteBuffer没有无符号的读取方法,所以自己实现一下,也可以直接用netty的Bytebuf,里面方法齐全- // 图方便直接返回int
- private int readUnsignedByte(ByteBuffer data) {
- return data.get() & 0xff;
- }
- // 图方便直接返回int
- private int readUnsignedShort(ByteBuffer data) {
- return data.getShort() & 0xffff;
- }
-
- private long readUnsignedInt(ByteBuffer data) {
- return data.getInt() & 0xffffffffL;
- }
复制代码 定义class文件结构
参考: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html- private static class ClassFileStructure {
- long magic;
- int minorVersion;
- int majorVersion;
- int constantPoolCount;
- ConstantPool[] constantPool;
- int accessFlags;
- int thisClass;
- int superClass;
- int interfacesCount;
- int[] interfaces;
- int fieldsCount;
- FieldInfo[] fields;
- int methodsCount;
- MethodInfo[] methods;
- int attributesCount;
- AttributeInfo[] attributes;
- }
复制代码 2 开始解析
2.1 magic- private void magic(ClassFileStructure structure, ByteBuffer data) {
- structure.magic = readUnsignedInt(data);
- }
复制代码 2.2 minorVersion- private void minorVersion(ClassFileStructure structure, ByteBuffer data) {
- structure.minorVersion = readUnsignedShort(data);
- }
复制代码 2.3 majorVersion- private void majorVersion(ClassFileStructure structure, ByteBuffer data) {
- structure.majorVersion = readUnsignedShort(data);
- }
复制代码 2.4 constantPoolCount- private void constantPoolCount(ClassFileStructure structure, ByteBuffer data) {
- structure.constantPoolCount = readUnsignedShort(data);
- }
复制代码 2.5 ConstantPool[]
ConstantPool不同tag解析方式不同,定义抽象类ConstantPool,子类按规则解析- private abstract static class ConstantPool {
- int tag;
- public ConstantPool(int tag) {
- this.tag = tag;
- }
- abstract void parse(ByteBuffer data);
- }
复制代码 子类实现ConstantPool
ConstantUtf8:- private class ConstantUtf8 extends ConstantPool {
- int length;
- byte[] bytes;
- public ConstantUtf8(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.length = readUnsignedShort(data);
- bytes = new byte[this.length];
- for (int i = 0; i < this.length; i++) {
- bytes[i] = (byte) readUnsignedByte(data);
- }
- }
- }
复制代码 ConstantMethodHandle:- private class ConstantMethodHandle extends ConstantPool {
- short referenceKind;
- int referenceIndex;
- public ConstantMethodHandle(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.referenceKind = (short) readUnsignedByte(data);
- this.referenceIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantMethodType:- private class ConstantMethodType extends ConstantPool {
- int descriptorIndex;
- public ConstantMethodType(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.descriptorIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantClass:- private class ConstantClass extends ConstantPool {
- int nameIndex;
- public ConstantClass(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.nameIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantClass:- private class ConstantClass extends ConstantPool {
- int nameIndex;
- public ConstantClass(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.nameIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantFieldref:- private class ConstantFieldref extends ConstantPool {
- int classIndex;
- int nameAndTypeIndex;
- public ConstantFieldref(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.classIndex = readUnsignedShort(data);
- this.nameAndTypeIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantMethodref:- private class ConstantMethodref extends ConstantPool {
- int classIndex;
- int nameAndTypeIndex;
- public ConstantMethodref(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.classIndex = readUnsignedShort(data);
- this.nameAndTypeIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantInterfaceMethodref:- private class ConstantInterfaceMethodref extends ConstantPool {
- int classIndex;
- int nameAndTypeIndex;
- public ConstantInterfaceMethodref(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.classIndex = readUnsignedShort(data);
- this.nameAndTypeIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantString:- private class ConstantString extends ConstantPool {
- int stringIndex;
- public ConstantString(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.stringIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantInteger:- private class ConstantInteger extends ConstantPool {
- long bytes;
- public ConstantInteger(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.bytes = readUnsignedInt(data);
- }
- }
复制代码 ConstantFloat:- private class ConstantFloat extends ConstantPool {
- long bytes;
- public ConstantFloat(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.bytes = readUnsignedInt(data);
- }
- }
复制代码 ConstantLong:- private class ConstantLong extends ConstantPool {
- long highBytes;
- long lowBytes;
- public ConstantLong(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.highBytes = readUnsignedInt(data);
- this.lowBytes = readUnsignedInt(data);
- }
- }
复制代码 ConstantDouble:- private class ConstantDouble extends ConstantPool {
- long highBytes;
- long lowBytes;
- public ConstantDouble(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.highBytes = readUnsignedInt(data);
- this.lowBytes = readUnsignedInt(data);
- }
- }
复制代码 ConstantNameAndType:- private class ConstantNameAndType extends ConstantPool {
- int nameIndex;
- int descriptorIndex;
- public ConstantNameAndType(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.nameIndex = readUnsignedShort(data);
- this.descriptorIndex = readUnsignedShort(data);
- }
- }
复制代码 ConstantInvokeDynamic:- private class ConstantInvokeDynamic extends ConstantPool {
- int bootstrapMethodAttrIndex;
- int nameAndTypeIndex;
- public ConstantInvokeDynamic(int tag) {
- super(tag);
- }
- @Override
- void parse(ByteBuffer data) {
- this.bootstrapMethodAttrIndex = readUnsignedShort(data);
- this.nameAndTypeIndex = readUnsignedShort(data);
- }
- }
复制代码 以上是所有 constantPool 子类型,现在开始解析
坑:“所有 8 字节常量都占用文件constant_pool表中的两个条目class。 如果
CONSTANT_Long_infoorCONSTANT_Double_info结构是constant_pool表中索引n处的项目,则池中的下一个可用项目位于索引n +2 处。
constant_pool 索引n +1 必须有效但被视为不可用 。 回想起来,让 8 字节常量占用两个常量池条目是一个糟糕的选择。”- private void constantPool(ClassFileStructure structure, ByteBuffer data) {
- structure.constantPool = new ConstantPool[structure.constantPoolCount - 1];
- for (int i = 0; i < structure.constantPool.length; i++) {
- int type = readUnsignedByte(data);
- int index = i;
- switch (type) {
- case 1: //
- structure.constantPool[i] = new ConstantUtf8(type);
- break;
- case 3: //
- structure.constantPool[i] = new ConstantInteger(type);
- break;
- case 4:
- structure.constantPool[i] = new ConstantFloat(type);
- break;
- case 5:
- structure.constantPool[i] = new ConstantLong(type);
- i++;// 占2位
- break;
- case 6:
- structure.constantPool[i] = new ConstantDouble(type);
- i++;// 占2位
- break;
- case 7: //
- structure.constantPool[i] = new ConstantClass(type);
- break;
- case 8: //
- structure.constantPool[i] = new ConstantString(type);
- break;
- case 9: //
- structure.constantPool[i] = new ConstantFieldref(type);
- break;
- case 10: //
- structure.constantPool[i] = new ConstantMethodref(type);
- break;
- case 11: //
- structure.constantPool[i] = new ConstantInterfaceMethodref(type);
- break;
- case 12: //
- structure.constantPool[i] = new ConstantNameAndType(type);
- break;
- case 15: //
- structure.constantPool[i] = new ConstantMethodHandle(type);
- break;
- case 16: //
- structure.constantPool[i] = new ConstantMethodType(type);
- break;
- case 18: //
- structure.constantPool[i] = new ConstantInvokeDynamic(type);
- break;
- default:
- throw new ParserException("class file parser exception");
- }
- structure.constantPool[index].parse(data);
- }
- }
复制代码 2.6 accessFlags- private void accessFlags(ClassFileStructure structure, ByteBuffer data) {
- structure.accessFlags = readUnsignedShort(data);
- }
复制代码 2.7 thisClass- private void thisClass(ClassFileStructure structure, ByteBuffer data) {
- structure.thisClass = readUnsignedShort(data);
- }
复制代码 2.8 superClass- private void superClass(ClassFileStructure structure, ByteBuffer data) {
- structure.superClass = readUnsignedShort(data);
- }
复制代码 2.9 interfacesCount- private void interfacesCount(ClassFileStructure structure, ByteBuffer data) {
- structure.interfacesCount = readUnsignedShort(data);
- }
复制代码 2.10 int[] interfaces- private void interfaces(ClassFileStructure structure, ByteBuffer data) {
- structure.interfaces = new int[structure.interfacesCount];
- for (int i = 0; i < structure.interfacesCount; i++) {
- structure.interfaces[i] = readUnsignedShort(data);
- }
- }
复制代码 2.11 fieldsCount- private ClassFile fieldsCount(ClassFileStructure structure, ByteBuffer data) {
- structure.fieldsCount = readUnsignedShort(data);
- return this;
- }
复制代码 2.12 FieldInfo[] fields
FieldInfo:- private class FieldInfo {
- int accessFlags;
- int nameIndex;
- int descriptorIndex;
- int attributesCount;
- AttributeInfo[] attributes;
- public FieldInfo parse(ByteBuffer data) {
- this.accessFlags = readUnsignedShort(data);
- this.nameIndex = readUnsignedShort(data);
- this.descriptorIndex = readUnsignedShort(data);
- this.attributesCount = readUnsignedShort(data);
- this.attributes = new AttributeInfo[attributesCount];
- for (int i = 0; i < this.attributesCount; i++) {
- this.attributes[i] = new AttributeInfo().parse(data);
- }
- return this;
- }
- }
复制代码 AttributeInfo:- private class AttributeInfo {
- int attributeNameIndex;
- long attributeLength;
- short[] info;
- public AttributeInfo parse(ByteBuffer data) {
- this.attributeNameIndex = readUnsignedShort(data);
- this.attributeLength = readUnsignedInt(data);
- this.info = new short[(int) attributeLength];
- for (int i = 0; i < this.attributeLength; i++) {
- this.info[i] = (short) readUnsignedByte(data);
- }
- return this;
- }
- }
复制代码- private void fields(ClassFileStructure structure, ByteBuffer data) {
- structure.fields = new FieldInfo[structure.fieldsCount];
- for (int i = 0; i < structure.fieldsCount; i++) {
- structure.fields[i] = new FieldInfo().parse(data);
- }
- }
复制代码 2.13 methodsCount- private ClassFile methodsCount(ClassFileStructure structure, ByteBuffer data) {
- structure.methodsCount = readUnsignedShort(data);
- return this;
- }
复制代码 2.14 MethodInfo[]
MethodInfo:- private class MethodInfo {
- int accessFlags;
- int nameIndex;
- int descriptorIndex;
- int attributesCount;
- AttributeInfo[] attributes;
- public MethodInfo parse(ByteBuffer data) {
- this.accessFlags = readUnsignedShort(data);
- this.nameIndex = readUnsignedShort(data);
- this.descriptorIndex = readUnsignedShort(data);
- this.attributesCount = readUnsignedShort(data);
- this.attributes = new AttributeInfo[attributesCount];
- for (int i = 0; i < this.attributesCount; i++) {
- this.attributes[i] = new AttributeInfo().parse(data);
- }
- return this;
- }
- }
复制代码- private void methods(ClassFileStructure structure, ByteBuffer data) {
- structure.methods = new MethodInfo[structure.methodsCount];
- for (int i = 0; i < structure.methodsCount; i++) {
- structure.methods[i] = new MethodInfo().parse(data);
- }
- }
复制代码 2.15 attributesCount- private void attributesCount(ClassFileStructure structure, ByteBuffer data) {
- structure.attributesCount = readUnsignedShort(data);
- }
复制代码 2.16 AttributeInfo[]- private void attributes(ClassFileStructure structure, ByteBuffer data) {
- structure.attributes = new AttributeInfo[structure.attributesCount];
- for (int i = 0; i < structure.attributesCount; i++) {
- structure.attributes[i] = new AttributeInfo().parse(data);
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |