Class文件解析

[复制链接]
发表于 2022-11-29 19:30:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×


1 准备工作

获取class文件byte[]
  1. public static byte[] getFileBytes(File file) {
  2.         try (FileInputStream fileInputStream = new FileInputStream(file)) {
  3.             int available = fileInputStream.available();
  4.             byte[] data=new byte[available];
  5.             fileInputStream.read(data,0,available-1);
  6.             return data;
  7.         } catch (Exception e) {
  8.             e.printStackTrace();
  9.         }
  10.         return null;
  11.     }
复制代码
这里使用jdk的ByteBuffer包装bytes
ByteBuffer data = ByteBuffer.wrap(getFileBytes(file));
因为ByteBuffer没有无符号的读取方法,所以自己实现一下,也可以直接用netty的Bytebuf,里面方法齐全
  1.     // 图方便直接返回int
  2.     private int readUnsignedByte(ByteBuffer data) {
  3.         return data.get() & 0xff;
  4.     }
  5.     // 图方便直接返回int
  6.     private int readUnsignedShort(ByteBuffer data) {
  7.         return data.getShort() & 0xffff;
  8.     }
  9.    
  10.     private long readUnsignedInt(ByteBuffer data) {
  11.         return data.getInt() & 0xffffffffL;
  12.     }
复制代码
定义class文件结构
参考:  https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
  1.     private static class ClassFileStructure {
  2.         long magic;
  3.         int minorVersion;
  4.         int majorVersion;
  5.         int constantPoolCount;
  6.         ConstantPool[] constantPool;
  7.         int accessFlags;
  8.         int thisClass;
  9.         int superClass;
  10.         int interfacesCount;
  11.         int[] interfaces;
  12.         int fieldsCount;
  13.         FieldInfo[] fields;
  14.         int methodsCount;
  15.         MethodInfo[] methods;
  16.         int attributesCount;
  17.         AttributeInfo[] attributes;
  18.     }
复制代码
2 开始解析

2.1 magic
  1.     private void magic(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.magic = readUnsignedInt(data);
  3.     }
复制代码
2.2 minorVersion
  1.     private void minorVersion(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.minorVersion = readUnsignedShort(data);
  3.     }
复制代码
2.3 majorVersion
  1.     private void majorVersion(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.majorVersion = readUnsignedShort(data);
  3.     }
复制代码
2.4 constantPoolCount
  1.    private void constantPoolCount(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.constantPoolCount = readUnsignedShort(data);
  3.    }
复制代码
2.5 ConstantPool[]
ConstantPool不同tag解析方式不同,定义抽象类ConstantPool,子类按规则解析
  1.     private abstract static class ConstantPool {
  2.     int tag;
  3.     public ConstantPool(int tag) {
  4.         this.tag = tag;
  5.     }
  6.     abstract void parse(ByteBuffer data);
  7. }
复制代码
子类实现ConstantPool
ConstantUtf8:
  1. private class ConstantUtf8 extends ConstantPool {
  2.     int length;
  3.     byte[] bytes;
  4.     public ConstantUtf8(int tag) {
  5.         super(tag);
  6.     }
  7.     @Override
  8.     void parse(ByteBuffer data) {
  9.         this.length = readUnsignedShort(data);
  10.         bytes = new byte[this.length];
  11.         for (int i = 0; i < this.length; i++) {
  12.             bytes[i] = (byte) readUnsignedByte(data);
  13.         }
  14.     }
  15. }
复制代码
ConstantMethodHandle:
  1. private class ConstantMethodHandle extends ConstantPool {
  2.     short referenceKind;
  3.     int referenceIndex;
  4.     public ConstantMethodHandle(int tag) {
  5.         super(tag);
  6.     }
  7.     @Override
  8.     void parse(ByteBuffer data) {
  9.         this.referenceKind = (short) readUnsignedByte(data);
  10.         this.referenceIndex = readUnsignedShort(data);
  11.     }
  12. }
复制代码
ConstantMethodType:
  1. private class ConstantMethodType extends ConstantPool {
  2.     int descriptorIndex;
  3.     public ConstantMethodType(int tag) {
  4.         super(tag);
  5.     }
  6.     @Override
  7.     void parse(ByteBuffer data) {
  8.         this.descriptorIndex = readUnsignedShort(data);
  9.     }
  10. }
复制代码
ConstantClass:
  1. private class ConstantClass extends ConstantPool {
  2.     int nameIndex;
  3.     public ConstantClass(int tag) {
  4.         super(tag);
  5.     }
  6.     @Override
  7.     void parse(ByteBuffer data) {
  8.         this.nameIndex = readUnsignedShort(data);
  9.     }
  10. }
复制代码
ConstantClass:
  1.    private class ConstantClass extends ConstantPool {
  2.     int nameIndex;
  3.     public ConstantClass(int tag) {
  4.         super(tag);
  5.     }
  6.     @Override
  7.     void parse(ByteBuffer data) {
  8.         this.nameIndex = readUnsignedShort(data);
  9.     }
  10. }
复制代码
ConstantFieldref:
  1. private class ConstantFieldref extends ConstantPool {
  2.     int classIndex;
  3.     int nameAndTypeIndex;
  4.     public ConstantFieldref(int tag) {
  5.         super(tag);
  6.     }
  7.     @Override
  8.     void parse(ByteBuffer data) {
  9.         this.classIndex = readUnsignedShort(data);
  10.         this.nameAndTypeIndex = readUnsignedShort(data);
  11.     }
  12. }
复制代码
ConstantMethodref:
  1. private class ConstantMethodref extends ConstantPool {
  2.     int classIndex;
  3.     int nameAndTypeIndex;
  4.     public ConstantMethodref(int tag) {
  5.         super(tag);
  6.     }
  7.     @Override
  8.     void parse(ByteBuffer data) {
  9.         this.classIndex = readUnsignedShort(data);
  10.         this.nameAndTypeIndex = readUnsignedShort(data);
  11.     }
  12. }
复制代码
ConstantInterfaceMethodref:
  1. private class ConstantInterfaceMethodref extends ConstantPool {
  2.     int classIndex;
  3.     int nameAndTypeIndex;
  4.     public ConstantInterfaceMethodref(int tag) {
  5.         super(tag);
  6.     }
  7.     @Override
  8.     void parse(ByteBuffer data) {
  9.         this.classIndex = readUnsignedShort(data);
  10.         this.nameAndTypeIndex = readUnsignedShort(data);
  11.     }
  12. }
复制代码
ConstantString:
  1. private class ConstantString extends ConstantPool {
  2.     int stringIndex;
  3.     public ConstantString(int tag) {
  4.         super(tag);
  5.     }
  6.     @Override
  7.     void parse(ByteBuffer data) {
  8.         this.stringIndex = readUnsignedShort(data);
  9.     }
  10. }
复制代码
ConstantInteger:
  1. private class ConstantInteger extends ConstantPool {
  2.     long bytes;
  3.     public ConstantInteger(int tag) {
  4.         super(tag);
  5.     }
  6.     @Override
  7.     void parse(ByteBuffer data) {
  8.         this.bytes = readUnsignedInt(data);
  9.     }
  10. }
复制代码
ConstantFloat:
  1. private class ConstantFloat extends ConstantPool {
  2.     long bytes;
  3.     public ConstantFloat(int tag) {
  4.         super(tag);
  5.     }
  6.     @Override
  7.     void parse(ByteBuffer data) {
  8.         this.bytes = readUnsignedInt(data);
  9.     }
  10. }
复制代码
ConstantLong:
  1. private class ConstantLong extends ConstantPool {
  2.     long highBytes;
  3.     long lowBytes;
  4.     public ConstantLong(int tag) {
  5.         super(tag);
  6.     }
  7.     @Override
  8.     void parse(ByteBuffer data) {
  9.         this.highBytes = readUnsignedInt(data);
  10.         this.lowBytes = readUnsignedInt(data);
  11.     }
  12. }
复制代码
ConstantDouble:
  1.    private class ConstantDouble extends ConstantPool {
  2.         long highBytes;
  3.         long lowBytes;
  4.         public ConstantDouble(int tag) {
  5.             super(tag);
  6.         }
  7.         @Override
  8.         void parse(ByteBuffer data) {
  9.             this.highBytes = readUnsignedInt(data);
  10.             this.lowBytes = readUnsignedInt(data);
  11.         }
  12.     }
复制代码
ConstantNameAndType:
  1.   private class ConstantNameAndType extends ConstantPool {
  2.         int nameIndex;
  3.         int descriptorIndex;
  4.         public ConstantNameAndType(int tag) {
  5.             super(tag);
  6.         }
  7.         @Override
  8.         void parse(ByteBuffer data) {
  9.             this.nameIndex = readUnsignedShort(data);
  10.             this.descriptorIndex = readUnsignedShort(data);
  11.         }
  12.     }
复制代码
ConstantInvokeDynamic:
  1.   private class ConstantInvokeDynamic extends ConstantPool {
  2.         int bootstrapMethodAttrIndex;
  3.         int nameAndTypeIndex;
  4.         public ConstantInvokeDynamic(int tag) {
  5.             super(tag);
  6.         }
  7.         @Override
  8.         void parse(ByteBuffer data) {
  9.             this.bootstrapMethodAttrIndex = readUnsignedShort(data);
  10.             this.nameAndTypeIndex = readUnsignedShort(data);
  11.         }
  12.     }
复制代码
以上是所有 constantPool 子类型,现在开始解析
坑:“所有 8 字节常量都占用文件constant_pool表中的两个条目class。 如果
CONSTANT_Long_infoorCONSTANT_Double_info结构是constant_pool表中索引n处的项目,则池中的下一个可用项目位于索引n +2 处。
constant_pool 索引n +1 必须有效但被视为不可用 。 回想起来,让 8 字节常量占用两个常量池条目是一个糟糕的选择。”
  1. private void constantPool(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.constantPool = new ConstantPool[structure.constantPoolCount - 1];
  3.         for (int i = 0; i < structure.constantPool.length; i++) {
  4.             int type = readUnsignedByte(data);
  5.             int index = i;
  6.             switch (type) {
  7.                 case 1: //
  8.                     structure.constantPool[i] = new ConstantUtf8(type);
  9.                     break;
  10.                 case 3: //
  11.                     structure.constantPool[i] = new ConstantInteger(type);
  12.                     break;
  13.                 case 4:
  14.                     structure.constantPool[i] = new ConstantFloat(type);
  15.                     break;
  16.                 case 5:
  17.                     structure.constantPool[i] = new ConstantLong(type);
  18.                     i++;// 占2位
  19.                     break;
  20.                 case 6:
  21.                     structure.constantPool[i] = new ConstantDouble(type);
  22.                     i++;// 占2位
  23.                     break;
  24.                 case 7: //
  25.                     structure.constantPool[i] = new ConstantClass(type);
  26.                     break;
  27.                 case 8: //
  28.                     structure.constantPool[i] = new ConstantString(type);
  29.                     break;
  30.                 case 9: //
  31.                     structure.constantPool[i] = new ConstantFieldref(type);
  32.                     break;
  33.                 case 10: //
  34.                     structure.constantPool[i] = new ConstantMethodref(type);
  35.                     break;
  36.                 case 11: //
  37.                     structure.constantPool[i] = new ConstantInterfaceMethodref(type);
  38.                     break;
  39.                 case 12: //
  40.                     structure.constantPool[i] = new ConstantNameAndType(type);
  41.                     break;
  42.                 case 15: //
  43.                     structure.constantPool[i] = new ConstantMethodHandle(type);
  44.                     break;
  45.                 case 16: //
  46.                     structure.constantPool[i] = new ConstantMethodType(type);
  47.                     break;
  48.                 case 18: //
  49.                     structure.constantPool[i] = new ConstantInvokeDynamic(type);
  50.                     break;
  51.                 default:
  52.                     throw new ParserException("class file parser exception");
  53.             }
  54.             structure.constantPool[index].parse(data);
  55.         }
  56.     }
复制代码
2.6 accessFlags
  1.     private void accessFlags(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.accessFlags = readUnsignedShort(data);
  3.     }
复制代码
2.7 thisClass
  1.     private void thisClass(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.thisClass = readUnsignedShort(data);
  3.     }
复制代码
2.8 superClass
  1.     private void superClass(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.superClass = readUnsignedShort(data);
  3.     }
复制代码
2.9 interfacesCount
  1.     private void interfacesCount(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.interfacesCount = readUnsignedShort(data);
  3.     }
复制代码
2.10 int[] interfaces
  1.     private void interfaces(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.interfaces = new int[structure.interfacesCount];
  3.         for (int i = 0; i < structure.interfacesCount; i++) {
  4.             structure.interfaces[i] = readUnsignedShort(data);
  5.         }
  6.     }
复制代码
2.11 fieldsCount
  1.     private ClassFile fieldsCount(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.fieldsCount = readUnsignedShort(data);
  3.         return this;
  4.     }
复制代码
2.12 FieldInfo[] fields
FieldInfo:
  1. private class FieldInfo {
  2.         int accessFlags;
  3.         int nameIndex;
  4.         int descriptorIndex;
  5.         int attributesCount;
  6.         AttributeInfo[] attributes;
  7.         public FieldInfo parse(ByteBuffer data) {
  8.             this.accessFlags = readUnsignedShort(data);
  9.             this.nameIndex = readUnsignedShort(data);
  10.             this.descriptorIndex = readUnsignedShort(data);
  11.             this.attributesCount = readUnsignedShort(data);
  12.             this.attributes = new AttributeInfo[attributesCount];
  13.             for (int i = 0; i < this.attributesCount; i++) {
  14.                 this.attributes[i] = new AttributeInfo().parse(data);
  15.             }
  16.             return this;
  17.         }
  18.     }
复制代码
AttributeInfo:
  1.   private class AttributeInfo {
  2.         int attributeNameIndex;
  3.         long attributeLength;
  4.         short[] info;
  5.         public AttributeInfo parse(ByteBuffer data) {
  6.             this.attributeNameIndex = readUnsignedShort(data);
  7.             this.attributeLength = readUnsignedInt(data);
  8.             this.info = new short[(int) attributeLength];
  9.             for (int i = 0; i < this.attributeLength; i++) {
  10.                 this.info[i] = (short) readUnsignedByte(data);
  11.             }
  12.             return this;
  13.         }
  14.     }
复制代码
  1.     private void fields(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.fields = new FieldInfo[structure.fieldsCount];
  3.         for (int i = 0; i < structure.fieldsCount; i++) {
  4.             structure.fields[i] = new FieldInfo().parse(data);
  5.         }
  6.     }
复制代码
2.13 methodsCount
  1.     private ClassFile methodsCount(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.methodsCount = readUnsignedShort(data);
  3.         return this;
  4.     }
复制代码
2.14 MethodInfo[]
MethodInfo:
  1. private class MethodInfo {
  2.         int accessFlags;
  3.         int nameIndex;
  4.         int descriptorIndex;
  5.         int attributesCount;
  6.         AttributeInfo[] attributes;
  7.         public MethodInfo parse(ByteBuffer data) {
  8.             this.accessFlags = readUnsignedShort(data);
  9.             this.nameIndex = readUnsignedShort(data);
  10.             this.descriptorIndex = readUnsignedShort(data);
  11.             this.attributesCount = readUnsignedShort(data);
  12.             this.attributes = new AttributeInfo[attributesCount];
  13.             for (int i = 0; i < this.attributesCount; i++) {
  14.                 this.attributes[i] = new AttributeInfo().parse(data);
  15.             }
  16.             return this;
  17.         }
  18.     }
复制代码
  1.     private void methods(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.methods = new MethodInfo[structure.methodsCount];
  3.         for (int i = 0; i < structure.methodsCount; i++) {
  4.             structure.methods[i] = new MethodInfo().parse(data);
  5.         }
  6.     }
复制代码
2.15 attributesCount
  1.     private void attributesCount(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.attributesCount = readUnsignedShort(data);
  3.     }
复制代码
2.16 AttributeInfo[]
  1.     private void attributes(ClassFileStructure structure, ByteBuffer data) {
  2.         structure.attributes = new AttributeInfo[structure.attributesCount];
  3.         for (int i = 0; i < structure.attributesCount; i++) {
  4.             structure.attributes[i] = new AttributeInfo().parse(data);
  5.         }
  6.     }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表