package main
import (
"./constan"
"encoding/binary"
"encoding/json"
"fmt"
)
type Class struct {
Magic uint32 `json:"magic"` // 魔数
MinorVersionMin uint16 `json:"minor_version_min"` // 副版本号
MinorVersion uint16 `json:"minor_version"` //主版本号
ConstantPoolCount uint16 `json:"constant_pool_count"` //常量池计数器
ConstantPoolInfo []ConstantPoolInfo `json:"constant_pool_info"` // 常量池
AccessFlags uint16 `json:"access_flags"` //访问标志
ThisClass uint16 `json:"this_class"` //类索引,
SuperClass uint16 `json:"super_class"` //父类索引,
InterfaceCount uint16 `json:"interface_count"` //接口计数器
interfaces []interface{} `json:"interfaces"` //接口表
FieldsCount uint16 `json:"fields_count"` //字段计数器
FieldInfo []interface{} `json:"field_info"` //字段表
MethodCount uint16 `json:"method_count"` //方法计数器
MethodInfo []*Method `json:"method_info"` //方法表
AttributesCount uint16 `json:"attributes_count"` //属性计数器
AttributeInfo []Attribute `json:"attribute_info"`
}
func (c Class) PrintClassInfo() {
buf, err := json.MarshalIndent(c, "", " ") //格式化编码
if err != nil {
fmt.Println("err = ", err)
}
fmt.Println("buf = ", string(buf))
}
type ClassBytes struct {
Bytes []byte
Class *Class
}
func (C *ClassBytes) AnalysisClass() {
class := C.Class
//解析魔数
class.Magic = binary.BigEndian.Uint32(C.Bytes[:4])
//小版本号
class.MinorVersionMin = binary.BigEndian.Uint16(C.Bytes[4:6])
//大版本号
class.MinorVersionMin = binary.BigEndian.Uint16(C.Bytes[6:8])
//读取常量池
class.ConstantPoolCount = binary.BigEndian.Uint16(C.Bytes[8:10])
//去除已经读过的字节
C.Bytes = C.Bytes[10:]
if class.ConstantPoolCount != 0 {
//调用常量池读取方法
pool := C.AnalysisClassReadeConstantPool(int(class.ConstantPoolCount))
class.ConstantPoolInfo = pool
}
//访问控制
class.AccessFlags = binary.BigEndian.Uint16(C.Bytes[:2])
//类索引
class.ThisClass = binary.BigEndian.Uint16(C.Bytes[2:4])
//父类
class.SuperClass = binary.BigEndian.Uint16(C.Bytes[4:6])
//接口计数器
class.InterfaceCount = binary.BigEndian.Uint16(C.Bytes[6:8])
//先去除读过的字节
C.Bytes = C.Bytes[8:]
//判断是否用接口
if class.InterfaceCount != 0 {
//解析接口
}
//字段计数器
class.FieldsCount = binary.BigEndian.Uint16(C.Bytes[:2])
//先去除读过的字节
C.Bytes = C.Bytes[2:]
//判断是否有字段
if class.InterfaceCount != 0 {
//解析字段
}
//方法计数器
class.MethodCount = binary.BigEndian.Uint16(C.Bytes[:2])
//先去除读过的字节
C.Bytes = C.Bytes[2:]
//判断是否有方法
if class.MethodCount != 0 {
//解析方法
method := C.AnalysisClassReadeMethod(int(class.MethodCount))
class.MethodInfo = method
}
//属性计数器
class.AttributesCount = binary.BigEndian.Uint16(C.Bytes[:2])
//先去除读过的字节
C.Bytes = C.Bytes[2:]
//判断是否有属性
if class.AttributesCount != 0 {
//属性解析
attributes := C.AnalysisClassReadeAttributes(int(class.AttributesCount), class)
class.AttributeInfo = attributes
}
}
func (C *ClassBytes) AnalysisClassReadeAttributes(count int, class *Class) []Attribute {
var attribute []Attribute = make([]Attribute, count)
for i := 0; i < count; i++ {
//2字节名称
nameIndex := binary.BigEndian.Uint16(C.Bytes[:2])
info := class.ConstantPoolInfo[nameIndex]
//强转,接口转成结构体
utf8Info := info.(*ConstantUtf8Info)
//取出string
s := string(utf8Info.Bytes)
length := binary.BigEndian.Uint32(C.Bytes[2:6])
//取属性信息
bytes := C.Bytes[6 : 6+length]
C.Bytes = C.Bytes[6+length:]
switch s {
case constan.CODE:
//j解析code
codeAttribute := CodeAttribute{}
codeAttribute.AttributeNameIndex = nameIndex
codeAttribute.AttributeLength = length
//栈深
codeAttribute.MaxStack = binary.BigEndian.Uint16(bytes[:2])
//空间
codeAttribute.MaxLocals = binary.BigEndian.Uint16(bytes[2:4])
//指令长度
codeAttribute.CodeLengthInfo = binary.BigEndian.Uint32(bytes[4:8])
//指令
codeAttribute.CodeInfo = bytes[8 : 8+codeAttribute.CodeLengthInfo]
//异常
bytes = bytes[8+codeAttribute.CodeLengthInfo:]
codeAttribute.ExceptionTableLength = binary.BigEndian.Uint16(bytes[:2])
//先去除读过的字节
bytes = bytes[2:]
//判断是否有异常
if codeAttribute.ExceptionTableLength != 0 {
//异常
}
//其它属性
codeAttribute.AttributesCountInfo = binary.BigEndian.Uint16(bytes[:2])
//先去除读过的字节
bytes = bytes[2:]
//判断是否有属性
if codeAttribute.AttributeLength != 0 {
//其它属性
//递归
//这里注意递归不要改变原来的class的值
var c ClassBytes
c.Bytes = bytes
attributes := c.AnalysisClassReadeAttributes(int(codeAttribute.AttributesCountInfo), class)
codeAttribute.AttributeInfo = attributes
}
attribute[i] = codeAttribute
case constan.LINENUMBERTABLE:
//LINENUMBERTABLE
lineNumberTableAttribute := LineNumberTableAttribute{}
lineNumberTableAttribute.AttributeNameIndex = nameIndex
lineNumberTableAttribute.AttributeLength = length
lineNumberTableAttribute.Infos = bytes
attribute[i] = lineNumberTableAttribute
case constan.LOCALVARIABLETABLE:
//LOCALVARIABLETABLE
localVariableTable := LocalVariableTable{}
localVariableTable.AttributeNameIndex = nameIndex
localVariableTable.AttributeLength = length
localVariableTable.Infos = bytes
attribute[i] = localVariableTable
case constan.SOURCEFILE:
//SOURCEFILE
sourceFile := SourceFile{}
sourceFile.AttributeNameIndex = nameIndex
sourceFile.AttributeLength = length
sourceFile.Infos = bytes
attribute[i] = sourceFile
}
}
return attribute
}
func (C *ClassBytes) AnalysisClassReadeMethod(count int) []*Method {
var method []*Method = make([]*Method, count)
for i := 0; i < count; i++ {
m := Method{}
////访问标识
m.AccessFlags = binary.BigEndian.Uint16(C.Bytes[:2])
m.NameIndex = binary.BigEndian.Uint16(C.Bytes[2:4])
m.DescriptorIndex = binary.BigEndian.Uint16(C.Bytes[4:6])
m.AttributesCount = binary.BigEndian.Uint16(C.Bytes[6:8])
//先去除读过的字节
C.Bytes = C.Bytes[8:]
//判断是否有属性
if m.AttributesCount != 0 {
//属性解析
C.AnalysisClassReadeAttributes(int(m.AttributesCount), C.Class)
}
method[i] = &m
}
return method
}
func (C *ClassBytes) AnalysisClassReadeConstantPool(count int) []ConstantPoolInfo {
var constantPoolInfo []ConstantPoolInfo = make([]ConstantPoolInfo, count)
//这里较为复杂,先循环
for i := 1; i < count; i++ {
//读取tag
tag := C.Bytes[0]
switch tag {
case constan.CONSTANT_Class:
//类信息ConstantClassInfo
info := &ConstantClassInfo{}
info.Tag = tag
info.NameIndex = binary.BigEndian.Uint16(C.Bytes[1:3])
C.Bytes = C.Bytes[3:]
constantPoolInfo[i] = info
case constan.CONSTANT_Fieldref:
//字段
info := &ConstantFieldrefInfo{}
info.Tag = tag
info.ClassIndex = binary.BigEndian.Uint16(C.Bytes[1:3])
info.nameAndTypeIndex = binary.BigEndian.Uint16(C.Bytes[3:5])
C.Bytes = C.Bytes[5:]
constantPoolInfo[i] = info
case constan.CONSTANT_Methodref:
//方法ConstantMethodrefInfo
info := &ConstantMethodrefInfo{}
info.Tag = tag
info.ClassIndex = binary.BigEndian.Uint16(C.Bytes[1:3])
info.nameAndTypeIndex = binary.BigEndian.Uint16(C.Bytes[3:5])
C.Bytes = C.Bytes[5:]
constantPoolInfo[i] = info
case constan.CONSTANT_InterfaceMethodref:
case constan.CONSTANT_String:
//方法ConstantStringInfo
info :