View Javadoc

1   // jq_StaticField.java, created Mon Feb  5 23:23:20 2001 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Class;
5   
6   //friend jq_ClassLoader;
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   * @author  John Whaley <jwhaley@alum.mit.edu>
21   * @version $Id: jq_StaticField.java 1931 2004-09-22 22:17:47Z joewhaley $
22   */
23  public final class jq_StaticField extends jq_Field {
24  
25      // null if not a constant.
26      private Object constantValue;
27      
28      private HeapAddress address;
29      
30      // clazz, name, desc, access_flags are inherited
31      private jq_StaticField(jq_Class clazz, jq_NameAndDesc nd) {
32          super(clazz, nd);
33      }
34      // ONLY TO BE CALLED BY jq_ClassLoader!!!
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         // this reference may be to a superclass or superinterface.
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 }