1
2
3
4 package joeq.Class;
5
6
7
8 import java.util.HashMap;
9 import java.util.Map;
10 import java.io.DataInput;
11 import java.io.DataOutput;
12 import java.io.IOException;
13 import joeq.Memory.Address;
14 import joeq.Memory.HeapAddress;
15 import joeq.UTF.Utf8;
16 import jwutil.util.Assert;
17 import jwutil.util.Convert;
18
19
20
21
22
23 public final class jq_StaticField extends jq_Field {
24
25
26 private Object constantValue;
27
28 private HeapAddress address;
29
30
31 private jq_StaticField(jq_Class clazz, jq_NameAndDesc nd) {
32 super(clazz, nd);
33 }
34
35 static jq_StaticField newStaticField(jq_Class clazz, jq_NameAndDesc nd) {
36 return new jq_StaticField(clazz, nd);
37 }
38
39 public final int getWidth() {
40 if (type == jq_Primitive.LONG || type == jq_Primitive.DOUBLE)
41 return 8;
42 else
43 return 4;
44 }
45
46 public final void load(jq_StaticField that) {
47 this.access_flags = that.access_flags;
48 this.attributes = (Map)((HashMap)that.attributes).clone();
49 this.constantValue = that.constantValue;
50 state = STATE_LOADED;
51 }
52
53 public final void load(char access_flags, Map attributes) {
54 super.load(access_flags, attributes);
55 parseAttributes();
56 }
57
58 public final void load(char access_flags, DataInput in)
59 throws IOException, ClassFormatError {
60 super.load(access_flags, in);
61 parseAttributes();
62 }
63
64 private final void parseAttributes() throws ClassFormatError {
65 byte[] a = getAttribute("ConstantValue");
66 if (a != null) {
67 if (a.length != 2) throw new ClassFormatError();
68 char cpidx = Convert.twoBytesToChar(a, 0);
69 jq_Class clazz = getDeclaringClass();
70 switch (clazz.getCPtag(cpidx)) {
71 case CONSTANT_Long:
72 if (type != jq_Primitive.LONG)
73 throw new ClassFormatError();
74 constantValue = clazz.getCPasLong(cpidx);
75 break;
76 case CONSTANT_Float:
77 if (type != jq_Primitive.FLOAT)
78 throw new ClassFormatError();
79 constantValue = clazz.getCPasFloat(cpidx);
80 break;
81 case CONSTANT_Double:
82 if (type != jq_Primitive.DOUBLE)
83 throw new ClassFormatError();
84 constantValue = clazz.getCPasDouble(cpidx);
85 break;
86 case CONSTANT_String:
87 if (type != PrimordialClassLoader.getJavaLangString())
88 throw new ClassFormatError();
89 constantValue = clazz.getCPasString(cpidx);
90 break;
91 case CONSTANT_Integer:
92 if (!type.isPrimitiveType() ||
93 type == jq_Primitive.LONG ||
94 type == jq_Primitive.FLOAT ||
95 type == jq_Primitive.DOUBLE)
96 throw new ClassFormatError();
97 constantValue = clazz.getCPasInt(cpidx);
98 break;
99 default:
100 throw new ClassFormatError("Unknown tag "+clazz.getCPtag(cpidx)+" at cp index "+(int)cpidx);
101 }
102 }
103 state = STATE_LOADED;
104 }
105
106 public final jq_Member resolve() { return resolve1(); }
107 public final jq_StaticField resolve1() {
108 this.clazz.load();
109 if (this.state >= STATE_LOADED) return this;
110
111 jq_StaticField m = this.clazz.getStaticField(nd);
112 if (m != null) return m;
113 throw new NoSuchFieldError(this.toString());
114 }
115
116 public void dumpAttributes(DataOutput out, jq_ConstantPool.ConstantPoolRebuilder cpr) throws IOException {
117 if (constantValue != null) {
118 byte[] b = new byte[2]; Convert.charToTwoBytes(cpr.get(constantValue), b, 0);
119 attributes.put(Utf8.get("ConstantValue"), b);
120 }
121 super.dumpAttributes(out, cpr);
122 }
123
124 public final void sf_initialize(int[] static_data, int offset) {
125 Assert._assert(state == STATE_PREPARED);
126 state = STATE_SFINITIALIZED;
127 HeapAddress a = HeapAddress.addressOf(static_data);
128 if (a != null)
129 this.address = (HeapAddress) a.offset(offset);
130 }
131 public final HeapAddress getAddress() {
132 chkState(STATE_SFINITIALIZED);
133 return address;
134 }
135 public final void setValue(int v) {
136 getDeclaringClass().setStaticData(this, v);
137 }
138 public final void setValue(float v) {
139 getDeclaringClass().setStaticData(this, v);
140 }
141 public final void setValue(long v) {
142 getDeclaringClass().setStaticData(this, v);
143 }
144 public final void setValue(double v) {
145 getDeclaringClass().setStaticData(this, v);
146 }
147 public final void setValue(Object v) {
148 getDeclaringClass().setStaticData(this, v);
149 }
150 public final void setValue(Address v) {
151 getDeclaringClass().setStaticData(this, v);
152 }
153
154 public final boolean needsDynamicLink(jq_Method method) {
155 return getDeclaringClass().needsDynamicLink(method);
156 }
157 public final boolean isConstant() {
158 chkState(STATE_LOADED);
159 return constantValue != null;
160 }
161 public final Object getConstantValue() {
162 return constantValue;
163 }
164 public final boolean isStatic() {
165 return true;
166 }
167
168 public final void prepare() {
169 Assert._assert(state == STATE_LOADED);
170 state = STATE_PREPARED;
171 }
172 public final void unprepare() {
173 Assert._assert(state == STATE_PREPARED);
174 state = STATE_LOADED;
175 }
176
177 public void accept(jq_FieldVisitor mv) {
178 mv.visitStaticField(this);
179 super.accept(mv);
180 }
181
182 public static final jq_Class _class;
183 static {
184 _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Class/jq_StaticField;");
185 }
186 }