/
field_ref.go
64 lines (58 loc) · 1.35 KB
/
field_ref.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package rtda
import (
"fmt"
"github.com/rodbate/jvm-on-go/pkg/classfile"
)
type FieldRef struct {
MemberRef
field *Field
}
func newFieldRef(cp *ConstantPool, info *classfile.ConstantFieldRefInfo) *FieldRef {
fieldRef := &FieldRef{}
fieldRef.cp = cp
fieldRef.initMemberRef(&info.ConstantMemberRefInfo)
return fieldRef
}
func (ref *FieldRef) ResolvedField() *Field {
if ref.field != nil {
return ref.field
}
return ref.resolveFieldRef()
}
func (ref *FieldRef) resolveFieldRef() *Field {
fromClass := ref.cp.class
toClass := ref.ResolvedClass()
field := lookupField(toClass, ref.name, ref.descriptor)
if field == nil {
panic(fmt.Sprintf("java.lang.NoSuchField: %s,%s", ref.name, ref.descriptor))
}
if !field.IsAccessibleTo(fromClass) {
panic(fmt.Sprintf("java.lang.IllegalAccessError: field=%s:%s,class=%s",
ref.name, ref.descriptor, fromClass.name))
}
ref.field = field
return field
}
func lookupField(class *Class, name string, descriptor string) *Field {
if class == nil {
return nil
}
for _, f := range class.fields {
if f.Match(name, descriptor) {
return f
}
}
for _, iFace := range class.interfaces {
f := lookupField(iFace, name, descriptor)
if f != nil {
return f
}
}
if superClass := class.superClass; superClass != nil {
f := lookupField(superClass, name, descriptor)
if f != nil {
return f
}
}
return nil
}