Skip to content

Commit

Permalink
Merge pull request #8 from kekeon/feature
Browse files Browse the repository at this point in the history
read class file
  • Loading branch information
ciscoxll authored Dec 13, 2018
2 parents 0211684 + d573c13 commit d736638
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 0 deletions.
110 changes: 110 additions & 0 deletions jvm.com/classfile/class-file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package classfile

import "fmt"

type ClassFile struct {
minorVersion uint16
majorVersion uint16
constantPool ConstantPool
accessFlags uint16
thisClass uint16
superClass uint16
interfaces []uint16
fields []*MemberInfo
methods []*MemberInfo
attributes []AttributeInfo
}

func Parse(classData []byte) (cf *ClassFile, err error) {
defer func() {
if r := recover(); r != nil {
var ok bool
err, ok = r.(error)

if !ok {
err = fmt.Errorf("%v", r)
}
}
}()

cr := &ClassReader{classData}

cf = &ClassFile{}

cf.read(cr)

return
}

func (self *ClassFile) read(reader *ClassReader) {
self.readAndCheckMagic(reader)

self.readAndCheckVersion(reader)

self.constantPool = readConstantPool(reader)

self.accessFlags = reader.readUint16()

self.thisClass = reader.readUint16()

self.superClass = reader.readUint16()

self.interfaces = reader.readUint16s()

self.fields = readerMembers(reader, self.constantPool)

self.attributes = readAttributes(reader, self.constantPool)
}

func (self *ClassFile) MajorVersion() uint16 {
return self.majorVersion
}

func (self *ClassFile) ClassName() string {
return self.constantPool.getClassName(self.thisClass)
}

func (self *ClassFile) SuperClassName() string {
if self.superClass > 0 {
return self.constantPool.getClassName(self.superClass)
}

return ""

}

func (self *ClassFile) InterfaceNames() []string {
interfaceNames := make([]string, len(self.interfaces))

for i, cpIndex := range interfaceNames {
interfaceNames[i] = self.constantPool.getClassName(cpIndex)
}

return interfaceNames
}

func (self *ClassFile) readAndCheckMagic(reader *ClassReader) {
magic := reader.readUint32()

if magic != 0xCAFEBABE {
panic("java.lang.ClassFormatError:magic!")
}
}

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!")
}
64 changes: 64 additions & 0 deletions jvm.com/classfile/class-reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package classfile

import "encoding/binary"

type ClassReader struct {
data []byte
}

// read u1 type data
func (self *ClassReader) readUint8() uint8 {
val := self.data[0]

self.data = self.data[1:]

return val
}

// read u2 type data
func (self *ClassReader) readUint16() uint16 {
val := binary.BigEndian.Uint16(self.data)

self.data = self.data[2:]

return val
}

// read u4 type data
func (self *ClassReader) readUint32() uint32 {
val := binary.BigEndian.Uint32(self.data)

self.data = self.data[4:]

return val
}

// read uint64 type data
func (self *ClassReader) readUint64() uint64 {
val := binary.BigEndian.Uint64(self.data)

self.data = self.data[8:]

return val
}

// read uint16 type data
func (self *ClassReader) readUint16s() []uint16 {
n := self.readUint16()

s := make([]uint16, n)

for i := range s {
s[i] = self.readUint16()
}

return s
}

// read custom type data
func (self *ClassReader) readBytes(n uint32) []byte {
bytes := self.data[:n]
self.data = self.data[n:]

return bytes
}
27 changes: 27 additions & 0 deletions jvm.com/classfile/constant_pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package classfile

type ConstantInfo interface {
readInfo(read *ClassReader)
}

type ConstantPool []ConstantInfo

func readConstantPool(reader *ClassReader) ConstantPool {

}

func (self ConstantPool) getConstantInfo(index uint16) ConstantInfo {

}

func (self *ConstantPool) getNameAndType(index uint16) (string, string) {

}

func (self *ConstantPool) getClassName(index uint16) string {

}

func (self *ConstantPool) getUtf8(index uint16) string {

}

0 comments on commit d736638

Please sign in to comment.