首页IT科技安装classin解析程序包时出现问题(Class文件解析)

安装classin解析程序包时出现问题(Class文件解析)

时间2025-05-01 03:15:10分类IT科技浏览3859
导读:1 准备工作 获取class文件byte[]...

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); } }

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
企业网站SEO优化的完整指南(从研究到外部链接,全面了解优化步骤和注意事项) go语言做web服务器(一文带你快速入门 Go 语言微服务开发 – Dubbo Go 入门实践总结)