2.按照指定格式读取class 文件

2.1. class文件示例

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

public class ClassFileTest {
    public static final boolean FLAG = false;
    public static final byte BYTE = 123;
    public static final char X = 'X';
    public static final short SHORT = 12345;
    public static final int INT = 123456789;
    public static final long LONG = 1234567L;
    public static final float PI = 3.1415925F;
    public static final double E = 2.71828D;

    public ClassFileTest() {
    }

    public static void main(String[] args) {
        System.out.println("HelloWorld");
    }
}

更详细的请阅读 0.从0开始的手写java虚拟机-class文件示例解读
class file文件格式 : jvms官网
在这里插入图片描述

2.2.书写代码

func (self *ClassFile) read(reader *ClassReader) {
	self.readAndCheckMagic(reader) //检查class文件格式,0xCAFEBABE
	self.readAndCheckVersion(reader)  //检查class文件版本
	self.constant_pool_count = reader.readUint16()  //获取常量池中元素个数
	self.cp_info = readConstantPool(self.constant_pool_count, reader)  //解析常量池
	ConstantPoolInstance = self.cp_info //保存一个常量池示例供外部使用
	self.access_flags = reader.readUint16() //获取class文件访问权限
	self.this_class = reader.readUint16()  //获取当前的class,
	self.super_class = reader.readUint16()  //获取超类的class,其中java.lang.Object为空
	self.interfaces_count = reader.readUint16() //获取接口数量
	self.interfaces = reader.readUint16s(self.interfaces_count) //解析接口
	self.fields_count = reader.readUint16() //获取字段的数量
	self.fields = readMembers(self.fields_count, reader) //读取字段
	self.methods_count = reader.readUint16() //获取方法的数量
	self.methods = readMembers(self.methods_count, reader) //读取方法,注意此处和获取字段时的方法一致,因为两者的格式一致
	self.attributes_count = reader.readUint16() //获取属性的数量
	self.attributes = readAttributes(self.attributes_count, reader) //读取属性
}

2.2.1.检查class文件格式,0xCAFEBABE

func (self *ClassFile) readAndCheckMagic(reader *ClassReader) {
	magic := reader.readUint32()
	if magic != 0xCAFEBABE {
		panic("java.lang.ClassFormatError: magic!")
	}
}

2.2.2.检查class文件版本

func (self *ClassFile) readAndCheckVersion(reader *ClassReader) {
	self.minorVersion = reader.readUint16()
	self.majorVersion = reader.readUint16()
	switch self.majorVersion {
	case 45:
		return
	case 46, 47, 48, 49, 50, 51, 52:
		if self.minorVersion == 0 {
			return
		}
	}
	panic("java.lang.UnsupportedClassVersionError!")
}

2.2.3.解析常量池

如下图所示,常量池中装着如下所示的字段;
在这里插入图片描述

2.2.3.1.常量池工厂类

package classfile

import "fmt"

const (
	CONSTANT_Utf8               = 1
	CONSTANT_Integer            = 3
	CONSTANT_Float              = 4
	CONSTANT_Long               = 5
	Constant_Double             = 6
	CONSTANT_Class              = 7
	CONSTANT_String             = 8
	CONSTANT_Fieldref           = 9
	CONSTANT_Methodref          = 10
	CONSTANT_InterfaceMethodref = 11
	CONSTANT_NameAndType        = 12
	CONSTANT_MethodHandle       = 15
	CONSTANT_MethodType         = 16
	CONSTANT_Dynamic            = 17
	CONSTANT_invokedynamic      = 18
	CONSTANT_Module             = 19
	CONSTANT_Package            = 20
)

type ConstantInfo interface {
	readInfo(reader *ClassReader)
}

func readConstantInfo(reader *ClassReader) ConstantInfo {
	tag := reader.readUint8()
	c := newConstantInfo(tag)
	c.readInfo(reader)
	return c
}

func newConstantInfo(tag uint8) ConstantInfo {
	switch tag {
	case CONSTANT_Utf8:
		return &ConstantUtf8Info{}
	case CONSTANT_Integer:
		return &ConstantIntegerInfo{}
	case CONSTANT_Float:
		return &ConstantFloatInfo{}
	case CONSTANT_Long:
		return &ConstantLongInfo{}
	case Constant_Double:
		return &ConstantDoubleInfo{}
	case CONSTANT_Class:
		return &ConstantClassInfo{}
	case CONSTANT_String:
		return &ConstantStringInfo{}
	case CONSTANT_Fieldref:
		return &ConstantFieldRefInfo{}
	case CONSTANT_Methodref:
		return &ConstantMethodRefInfo{}
	case CONSTANT_InterfaceMethodref:
		return &ConstantInterfaceMethodRefInfo{}
	case CONSTANT_NameAndType:
		return &ConstantNameAndTypeInfo{}
	case CONSTANT_MethodHandle:
		return &ConstantMethodHandleInfo{}
	case CONSTANT_MethodType:
		return &ConstantMethodTypeInfo{}
	case CONSTANT_Dynamic:
		return &ConstantDynamicInfo{}
	case CONSTANT_invokedynamic:
		return &ConstantInvokeDynamicInfo{}
	case CONSTANT_Module:
		return &ConstantModuleInfo{}
	case CONSTANT_Package:
		return &ConstantPackageInfo{}
	default:
		tip := fmt.Sprintf("java.lang.ClassFormatError: no such tag(%v)", tag)
		panic(tip)
	}
}


2.2.3.2.CONSTANT_Utf8

在这里插入图片描述

package classfile

type ConstantUtf8Info struct {
	tag    uint8
	length uint16
	bytes  []byte
}

func (self *ConstantUtf8Info) readInfo(reader *ClassReader) {
	self.tag = 1
	self.length = reader.readUint16()
	bytes := reader.readBytes(uint32(self.length))
	self.bytes = make([]byte, self.length)
	for index, val := range bytes {
		self.bytes[index] = val
	}
}

2.2.3.3.CONSTANT_Integer

在这里插入图片描述

package classfile

type ConstantIntegerInfo struct {
	tag uint8
	val int32
}

func (self *ConstantIntegerInfo) readInfo(reader *ClassReader) {
	self.tag = 3
	bytes := reader.readUint32()
	self.val = int32(bytes)
}

2.2.3.4.CONSTANT_Float

在这里插入图片描述

package classfile

import "math"

type ConstantFloatInfo struct {
	tag uint8
	val float32
}

func (self *ConstantFloatInfo) readInfo(reader *ClassReader) {
	self.tag = 4
	val := reader.readUint32()
	self.val = math.Float32frombits(val)
}

2.2.3.5.CONSTANT_Long

package classfile

type ConstantLongInfo struct {
	tag uint8
	//high_bytes uint32
	//low_bytes  uint32
	val int64
}

func (self *ConstantLongInfo) readInfo(reader *ClassReader) {
	self.tag = 5
	bytes := reader.readUint64()
	self.val = int64(bytes)
}

2.2.3.6.CONSTANT_Double

在这里插入图片描述

package classfile

import "math"

type ConstantDoubleInfo struct {
	tag uint8
	//uint32 high_butes
	//uint32 low_bytes
	val float64
}

func (self *ConstantDoubleInfo) readInfo(reader *ClassReader) {
	bytes := reader.readUint64()
	self.tag = 6
	self.val = math.Float64frombits(bytes)
}

2.2.3.7.CONSTANT_Class

在这里插入图片描述

package classfile

type ConstantClassInfo struct {
	tag        uint8
	name_index uint16
}

func (self *ConstantClassInfo) readInfo(reader *ClassReader) {
	self.tag = 7
	self.name_index =  reader.readUint16()
}

2.2.3.8.CONSTANT_String

在这里插入图片描述

package classfile

type ConstantStringInfo struct {
	tag          uint8
	string_index uint16
}

func (self *ConstantStringInfo) readInfo(reader *ClassReader) {
	self.tag = 8
	self.string_index = reader.readUint16()
}

2.2.3.9.CONSTANT_Fieldref

在这里插入图片描述

package classfile

type ConstantFieldRefInfo struct {
	tag                 uint8
	class_index         uint16
	name_and_type_index uint16
}

func (self *ConstantFieldRefInfo) readInfo(reader *ClassReader) {
	self.tag = 9
	self.class_index = reader.readUint16()
	self.name_and_type_index = reader.readUint16()
}

2.2.3.10.CONSTANT_Methodref

在这里插入图片描述

package classfile

type ConstantMethodRefInfo struct {
	tag                 uint8
	class_index         uint16
	name_and_type_index uint16
}

func (self *ConstantMethodRefInfo) readInfo(reader *ClassReader) {
	self.tag = 10
	self.class_index = reader.readUint16()
	self.name_and_type_index = reader.readUint16()
}

2.2.3.11.CONSTANT_InterfaceMethodref

在这里插入图片描述

package classfile

type ConstantInterfaceMethodRefInfo struct {
	tag                 uint8
	class_index         uint16
	name_and_type_index uint16
}

func (self *ConstantInterfaceMethodRefInfo) readInfo(reader *ClassReader) {
	self.tag = 11
	self.class_index = reader.readUint16()
	self.name_and_type_index = reader.readUint16()
}

2.2.3.12.CONSTANT_NameAndType

在这里插入图片描述

package classfile

//B -> byte
//S -> short
//C -> char
//I -> int
//J -> long
//F -> float
//D -> double

/*
e.g.
void run() -> ()V
String toString() -> ()Ljava.lang.String
void main(String[] args) -> (Ljava.lang.String;)V
int max(float x, float y) -> (FF)I
int binarySearch(long[]a, long key) -> ([JJ)I


*/

type ConstantNameAndTypeInfo struct {
	tag              uint8
	name_index       uint16
	descriptor_index uint16
}

func (self *ConstantNameAndTypeInfo) readInfo(reader *ClassReader) {
	self.tag = 12
	self.name_index = reader.readUint16()
	self.descriptor_index = reader.readUint16()
}

2.2.3.15.CONSTANT_MethodHandle

在这里插入图片描述

package classfile

type ConstantMethodHandleInfo struct {
	tag             uint8
	reference_kind  uint16
	reference_index uint16
}

func (self *ConstantMethodHandleInfo) readInfo(reader *ClassReader) {
	self.tag = 15
	self.reference_kind = reader.readUint16()
	self.reference_index = reader.readUint16()
}

2.2.3.16.CONSTANT_Methodtype

在这里插入图片描述

package classfile

type ConstantMethodTypeInfo struct {
	tag              uint8
	descriptor_index uint16
}

func (self*ConstantMethodTypeInfo) readInfo(reader*ClassReader)  {
	self.tag = 16
	self.descriptor_index = reader.readUint16()
}

2.2.3.18.CONSTANT_Invokedynamic

在这里插入图片描述

package classfile

type ConstantInvokeDynamicInfo struct {
	tag                         uint8
	bootstrap_method_attr_index uint16
	nam_and_type_index          uint16
}

func (self *ConstantInvokeDynamicInfo) readInfo(reader *ClassReader) {
	self.tag = 18
	self.bootstrap_method_attr_index = reader.readUint16()
	self.nam_and_type_index = reader.readUint16()
}

// 以上即为常量池的实现,鉴于篇幅原因,就先写这些


版权声明:本文为Yuan_xii原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/Yuan_xii/article/details/121409457