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 版权协议,转载请附上原文出处链接和本声明。