KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gov > nasa > jpf > jvm > ClassInfo


1 //
2
// Copyright (C) 2005 United States Government as represented by the
3
// Administrator of the National Aeronautics and Space Administration
4
// (NASA). All Rights Reserved.
5
//
6
// This software is distributed under the NASA Open Source Agreement
7
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
8
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
9
// directory tree for the complete NOSA document.
10
//
11
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
12
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
13
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
14
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
15
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
16
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
17
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
18
//
19
package gov.nasa.jpf.jvm;
20
21 import gov.nasa.jpf.*;
22 import gov.nasa.jpf.jvm.bytecode.Instruction;
23 import gov.nasa.jpf.util.*;
24 import gov.nasa.jpf.util.Debug;
25
26 import java.io.*;
27
28 import java.util.*;
29
30 import org.apache.bcel.classfile.*;
31 import org.apache.bcel.util.SyntheticRepository;
32 import org.apache.bcel.generic.ConstantPoolGen;
33
34
35 /**
36  * Describes the JVM's view of a java class. Contains descriptions of the
37  * static and dynamic fields, methods, and information relevant to the
38  * class.
39  */

40 public class ClassInfo {
41   /**
42    * this is our BCEL class repository. Note that this actually might be
43    * turned into a call or ClassInfo instance field if we ever support
44    * ClassLoaders (for now we keep it simple)
45    */

46   protected static SyntheticRepository repository;
47   
48   /**
49    * Map of the loaded classes.
50    */

51   protected static Hashtable loadedClasses;
52   
53   /**
54    * optionally used to determine atomic methods of a class (during class loading)
55    */

56   protected static Attributor attributor;
57   
58   /**
59    * here we get infinitly recursive, so keep it around for
60    * identity checks
61    */

62   static ClassInfo classClassInfo;
63   
64   /*
65    * some distinguished classInfos we keep around for efficiency reasons
66    */

67   static ClassInfo objectClassInfo;
68   static ClassInfo stringClassInfo;
69   static ClassInfo weakRefClassInfo;
70   static ClassInfo refClassInfo;
71   
72   static FieldInfo[] emptyFields = new FieldInfo[0];
73     
74   /**
75    * Initializes a class. A class is initialized atomically without being
76    * interleaved with any other thread.
77    *
78    * <2do> pcm - wrong. static init of a class is only synced on the class
79    * object itself
80    */

81   static int level;
82   
83   /**
84    * Name of the class.
85    */

86   protected final String JavaDoc name;
87   
88   // various class attributes
89
protected boolean isClass = true;
90   protected boolean isWeakReference = false;
91   protected MethodInfo finalizer = null;
92   protected boolean isArray = false;
93   protected boolean isReferenceArray = false;
94   
95   
96   /** type based object attributes (for GC, partial order reduction and
97    * property checks)
98    */

99   protected int elementInfoAttrs = 0;
100   
101   /**
102    * all our declared methods (we don't flatten, this is not
103    * a high-performance VM)
104    */

105   protected final Map methods;
106   
107   /**
108    * our instance fields.
109    * Note these are NOT flattened, i.e. only contain the declared ones
110    */

111   protected FieldInfo[] iFields;
112   
113   /** the storage size of instances of this class (stored as an int[]) */
114   protected int instanceDataSize;
115   
116   /** where in the instance data array (int[]) do our declared fields start */
117   protected int instanceDataOffset;
118   
119   /** total number of instance fields (flattened, not only declared ones) */
120   protected int nInstanceFields;
121   
122   /**
123    * our static fields. Again, not flattened
124    */

125   protected FieldInfo[] sFields;
126   
127   /** the storage size of static fields of this class (stored as an int[]) */
128   protected int staticDataSize;
129   
130   protected final ClassInfo superClass;
131   
132   /**
133    * Interfaces implemented by the class.
134    */

135   protected final Set interfaces;
136   
137   /** all interfaces (parent interfaces and interface parents) - lazy eval */
138   protected Set allInterfaces;
139   
140   /** Name of the package. */
141   protected final String JavaDoc packageName;
142   
143   /** Name of the file which contains the source of this class. */
144   protected String JavaDoc sourceFileName;
145   
146   /**
147    * this is the object we use to execute methods in the underlying JVM
148    * (it replaces Reflection)
149    * <2do> pcm - set this private once MethodInfo is cleaned up
150    */

151   NativePeer nativePeer;
152   
153   /** Source file associated with the class.*/
154   protected Source source;
155
156   static String JavaDoc[] assertionPatterns;
157   boolean enableAssertions;
158   
159   static boolean init (Config config) throws Config.Exception {
160     loadedClasses = new Hashtable();
161     classClassInfo = null;
162     objectClassInfo = null;
163     stringClassInfo = null;
164     weakRefClassInfo = null;
165
166     setSourceRoots(config);
167     repository = createRepository(config);
168     
169     attributor = (Attributor)config.getEssentialInstance("vm.attributor.class",
170                                                          Attributor.class);
171     
172     assertionPatterns = config.getStringArray("vm.enable_assertions");
173         
174     return true;
175   }
176     
177   /**
178    * ClassInfo ctor used for builtin types (arrays and primitive types)
179    * i.e. classes we don't have class files for
180    */

181   protected ClassInfo (String JavaDoc builtinClassName) {
182     isArray = (builtinClassName.charAt(0) == '[');
183     isReferenceArray = isArray && builtinClassName.endsWith(";");
184     
185     name = builtinClassName;
186     
187     Debug.print(Debug.DEBUG, "generating builtin class ");
188     Debug.println(Debug.DEBUG, name);
189     
190     packageName = ""; // builtin classes don't reside in java.lang !
191
sourceFileName = null;
192     source = null;
193     
194     // no fields
195
iFields = emptyFields;
196     sFields = emptyFields;
197     
198     if (isArray) {
199       superClass = objectClassInfo;
200       interfaces = loadArrayInterfaces();
201       methods = loadArrayMethods();
202     } else {
203       superClass = null; // strange, but true, a 'no object' class
204
interfaces = loadBuiltinInterfaces(name);
205       methods = loadBuiltinMethods(name);
206     }
207     
208     enableAssertions = true; // doesn't really matter - no code associated
209

210     loadedClasses.put(name, this);
211   }
212   
213   /**
214    * Creates a new class from the JavaClass information.
215    */

216   protected ClassInfo (JavaClass jc) {
217     name = jc.getClassName();
218     
219     Debug.print(Debug.DEBUG, "loading class ");
220     Debug.println(Debug.DEBUG, name);
221     
222     loadedClasses.put(name, this);
223     
224     if ((objectClassInfo == null) && name.equals("java.lang.Object")) {
225       objectClassInfo = this;
226     } else if ((classClassInfo == null) && name.equals("java.lang.Class")) {
227       classClassInfo = this;
228     } else if ((stringClassInfo == null) && name.equals("java.lang.String")) {
229       stringClassInfo = this;
230     } else if ((weakRefClassInfo == null) &&
231                name.equals("java.lang.ref.WeakReference")) {
232       weakRefClassInfo = this;
233     } else if ((refClassInfo == null) && name.equals("java.lang.ref.Reference")) {
234       refClassInfo = this;
235     }
236     
237     isClass = jc.isClass();
238     superClass = loadSuperClass(jc);
239     
240     interfaces = loadInterfaces(jc);
241     packageName = jc.getPackageName();
242     
243     iFields = loadInstanceFields(jc);
244     instanceDataSize = computeInstanceDataSize();
245     instanceDataOffset = computeInstanceDataOffset();
246     nInstanceFields = (superClass != null) ?
247       superClass.nInstanceFields + iFields.length : iFields.length;
248     
249     sFields = loadStaticFields(jc);
250     staticDataSize = computeStaticDataSize();
251     
252     methods = loadMethods(jc);
253     
254     // Used to execute native methods (in JVM land).
255
// This needs to be initialized AFTER we get our
256
// MethodInfos, since it does a reverse lookup to determine which
257
// ones are handled by the peer (by means of setting MethodInfo attributes)
258
nativePeer = NativePeer.getNativePeer(this);
259     
260     sourceFileName = jc.getSourceFileName();
261     
262     // bcel seems to behave differently on Windows, returning <Unknown>,
263
// which gives us problems when writing/reading XML traces
264
if (sourceFileName.equalsIgnoreCase("<Unknown>")) {
265       sourceFileName = "Unkown";
266     }
267     
268     if (packageName.length() > 0) {
269       sourceFileName = packageName.replace('.', File.separatorChar) +
270         File.separator + sourceFileName;
271     }
272     
273     source = null;
274     
275     isWeakReference = isWeakReference0();
276     finalizer = getFinalizer0();
277     
278     // get type specific object and field attributes
279
elementInfoAttrs = loadElementInfoAttrs(jc);
280     
281     // the corresponding java.lang.Class object gets set when we initialize
282
// this class from StaticArea.newClass() - we don't know the
283
// DynamicArea (Heap) here, until we turn this into a global object
284

285     enableAssertions = getAssertionStatus();
286     
287     // be advised - we don't have fields initialized yet
288
JVM.getVM().notifyClassLoaded(this);
289   }
290   
291   boolean getAssertionStatus () {
292     if ((assertionPatterns == null) || (assertionPatterns.length == 0)){
293       return false;
294     } else if ("*".equals(assertionPatterns[0])) {
295       return true;
296     } else {
297       for (int i=0; i<assertionPatterns.length; i++) {
298         if (name.matches(assertionPatterns[i])) { // Ok, not very efficient
299
return true;
300         }
301       }
302       
303       return false;
304     }
305   }
306   
307   public boolean isArray () {
308     return isArray;
309   }
310   
311   public boolean isReferenceArray () {
312     return isReferenceArray;
313   }
314   
315   /**
316    * Loads the class specified.
317    * @param cname The fully qualified name of the class to load.
318    * @return Returns the ClassInfo for the classname passed in,
319    * or null.
320    */

321   public static synchronized ClassInfo getClassInfo (String JavaDoc cname) {
322     JavaClass jc = null;
323     
324     if (cname == null) {
325       return null;
326     }
327     
328     cname = cname.replace('/', '.');
329     
330     ClassInfo ci = (ClassInfo) loadedClasses.get(cname);
331     
332     if (ci == null) {
333       if (isBuiltinClass(cname)) {
334         // this is a array class - there's no class file for this, it
335
// gets automatically generated by the VM
336
ci = new ClassInfo(cname);
337       } else {
338         try {
339           jc = repository.loadClass(cname);
340         } catch (ClassNotFoundException JavaDoc x) {
341           throw new JPFException("could not load class " + cname);
342         }
343         
344         // <?> pm - looks like a memory housekeeping issue (since we cache
345
// ourselves). Might have to be changed with JavaClass/ClassInfo unification
346
// and/or ClassLoader support
347
repository.clear();
348         
349         ci = new ClassInfo(jc);
350       }
351     }
352     
353     return ci;
354   }
355   
356   public boolean areAssertionsEnabled() {
357     return enableAssertions;
358   }
359   
360   public int getClassObjectRef () {
361     // NOTE - we can't simply store our classObject, because this can be
362
// backtracked to a state where the class wasn't loaded yet, and hence
363
// the classObject would be different. Maybe we should pin classObjects
364
// down and store them here
365
StaticArea sa = JVM.getVM().getStaticArea();
366     
367     // <2do> Watch out, it's never null, is that what we want?
368
StaticElementInfo sei = sa.get(name);
369     
370     return (sei != null) ? sei.getClassObjectRef() : -1;
371   }
372   
373   /**
374    * Note that 'uniqueName' is the name plus the argument type part of the
375    * signature, i.e. everything that's relevant for overloading
376    * (besides saving some const space, we also ease reverse lookup
377    * of natives that way).
378    * Note also that we don't have to make any difference between
379    * class and instance methods, because that just matters in the
380    * INVOKExx instruction, when looking up the relevant ClassInfo to start
381    * searching in (either by means of the object type, or by means of the
382    * constpool classname entry).
383    */

384   public MethodInfo getMethod (String JavaDoc uniqueName, boolean isRecursiveLookup) {
385     MethodInfo mi = null;
386     
387     if (uniqueName.charAt(uniqueName.length() - 1) != ')') {
388       // somebody slipped us a full signature?
389
uniqueName = uniqueName.substring(0, uniqueName.indexOf(')') + 1);
390     }
391     
392     mi = (MethodInfo) methods.get(uniqueName);
393     
394     if ((mi == null) && isRecursiveLookup && (superClass != null)) {
395       mi = superClass.getMethod(uniqueName, true);
396     }
397     
398     return mi;
399   }
400   
401   public FieldInfo getStaticField (String JavaDoc clsBase, String JavaDoc fName) {
402     FieldInfo fi;
403     ClassInfo c = getClassBase(clsBase);
404     
405     while (c != null) {
406       fi = c.getDeclaredStaticField(fName);
407       if (fi != null) return fi;
408       c = c.superClass;
409     }
410     
411     return null;
412   }
413   
414   public FieldInfo getStaticField (String JavaDoc fname) {
415     return getStaticField(null, fname);
416   }
417   
418   /**
419    * FieldInfo lookup in the static fields that are declared in this class
420    * <2do> pcm - should employ a map at some point, but it's usually not that
421    * important since we can cash the returned FieldInfo in the PUT/GET_STATIC insns
422    */

423   public FieldInfo getDeclaredStaticField (String JavaDoc fName) {
424     for (int i=0; i<sFields.length; i++) {
425       if (sFields[i].getName().equals(fName)) return sFields[i];
426     }
427     
428     return null;
429   }
430   
431   /**
432    * base relative FieldInfo lookup - the workhorse
433    * <2do> again, should eventually use Maps
434    * @param clsBase - the class where we start the lookup (self or some super)
435    * @param fName - the field name
436    */

437   public FieldInfo getInstanceField (String JavaDoc clsBase, String JavaDoc fName) {
438     FieldInfo fi;
439     ClassInfo c = getClassBase(clsBase);
440     
441     while (c != null) {
442       fi = c.getDeclaredInstanceField(fName);
443       if (fi != null) return fi;
444       c = c.superClass;
445     }
446     
447     return null;
448   }
449   
450   /**
451    * complete bottom-up FieldInfo lookup
452    */

453   public FieldInfo getInstanceField (String JavaDoc fName) {
454     return getInstanceField(null, fName);
455   }
456   
457   /**
458    * FieldInfo lookup in the fields that are declared in this class
459    */

460   public FieldInfo getDeclaredInstanceField (String JavaDoc fName) {
461     for (int i=0; i<iFields.length; i++) {
462       if (iFields[i].getName().equals(fName)) return iFields[i];
463     }
464     
465     return null;
466   }
467   
468   
469   /**
470    * consult nativePeer to check if method is deterministic
471    */

472   public boolean isMethodCondDeterministic (ThreadInfo th, MethodInfo mi) {
473     if (nativePeer != null) {
474       return nativePeer.isMethodCondDeterministic(th, mi);
475     }
476     
477     return false;
478   }
479   
480   /**
481    * consult nativePeer to check if method is executable
482    */

483   public boolean isMethodCondExecutable (ThreadInfo th, MethodInfo mi) {
484     if (nativePeer != null) {
485       return nativePeer.isMethodCondExecutable(th, mi);
486     }
487     
488     return false;
489   }
490   
491   /**
492    * Returns the name of the class.
493    */

494   public String JavaDoc getName () {
495     return name;
496   }
497   
498   public String JavaDoc getPackageName () {
499     return packageName;
500   }
501   
502   public int getFieldAttrs (int fieldIndex) {
503     return 0;
504   }
505   
506   public int getElementInfoAttrs () {
507     return elementInfoAttrs;
508   }
509   
510   public Source getSource () {
511     if (source == null) {
512       source = loadSource();
513     }
514     
515     return source;
516   }
517   
518   public String JavaDoc getSourceFileName () {
519     return sourceFileName;
520   }
521   
522   /**
523    * Returns the information about a static field.
524    */

525   public FieldInfo getStaticField (int index) {
526     return sFields[index];
527   }
528   
529   /**
530    * Returns the name of a static field.
531    */

532   public String JavaDoc getStaticFieldName (int index) {
533     return getStaticField(index).getName();
534   }
535   
536   /**
537    * Checks if a static method call is deterministic, but only for
538    * abtraction based determinism, due to Bandera.choose() calls
539    */

540   public boolean isStaticMethodAbstractionDeterministic (ThreadInfo th,
541                                                          MethodInfo mi) {
542     // Reflection r = reflection.instantiate();
543
// return r.isStaticMethodAbstractionDeterministic(th, mi);
544
// <2do> - still has to be implemented
545
return true;
546   }
547   
548   /**
549    * Return the super class.
550    */

551   public ClassInfo getSuperClass () {
552     return superClass;
553   }
554   
555   /**
556    * return the ClassInfo for the provided superclass name. If this is equal
557    * to ourself, return this (a little bit strange if we hit it in the first place)
558    */

559   public ClassInfo getSuperClass (String JavaDoc clsName) {
560     if (clsName.equals(name)) return this;
561     
562     if (superClass != null) {
563       return superClass.getSuperClass(clsName);
564     } else {
565       return null;
566     }
567   }
568   
569   public boolean isInstanceOf (ClassInfo ci) {
570     ClassInfo c = this;
571     do {
572       if (c == ci) {
573         return true;
574       }
575       c = c.superClass;
576     } while (c != null);
577     
578     return false;
579   }
580   
581   /**
582    * Returns true if the class is a system class.
583    */

584   public boolean isSystemClass () {
585     return name.startsWith("java.") || name.startsWith("javax.");
586   }
587   
588   /**
589    * Returns the type of a class.
590    */

591   public String JavaDoc getType () {
592     return "L" + name.replace('.', '/') + ";";
593   }
594   
595   /**
596    * is this a (subclass of) WeakReference? this must be efficient, since it's
597    * called in the mark phase on all live objects
598    */

599   public boolean isWeakReference () {
600     return isWeakReference;
601   }
602   
603   /**
604    * note this only returns true is this is really the java.lang.ref.Reference classInfo
605    */

606   public boolean isRefClass () {
607     return (this == refClassInfo);
608   }
609   
610   /**
611    * Creates the fields for an object.
612    */

613   public Fields createInstanceFields () {
614     return new DynamicFields(getType(), this);
615   }
616   
617   boolean hasRefField (int ref, Fields fv) {
618     ClassInfo c = this;
619     
620     do {
621       FieldInfo[] fia = c.iFields;
622       for (int i=0; i<fia.length; i++) {
623         FieldInfo fi = c.iFields[i];
624         if (fi.isReference() && (fv.getIntValue( fi.getStorageOffset()) == ref)) return true;
625       }
626       c = c.superClass;
627     } while (c != null);
628     
629     return false;
630   }
631   
632   boolean hasImmutableInstances () {
633     return ((elementInfoAttrs & ElementInfo.ATTR_IMMUTABLE) != 0);
634   }
635   
636   public Instruction executeNativeMethod (ThreadInfo th, MethodInfo mi) {
637     if (nativePeer != null) {
638       return nativePeer.executeMethod(th, mi);
639     }
640     
641     return th.createAndThrowException("java.lang.UnsatisfiedLinkError",
642                                       name + '.' + mi.getName() +
643                                         " (no peer)");
644   }
645   
646   public static boolean exists (String JavaDoc cname) {
647     // <?> pcm - is this really intended to load the thing?
648
// (I assume not, and therefor replace repository.lookupClass())
649
return (repository.findClass(cname) != null);
650   }
651   
652   public void initializeClass (ThreadInfo th) {
653     if (th == null) {
654       return; // no thread stack, nothing we can execute (called from vm.init)
655
}
656     
657     Debug.print(Debug.DEBUG, "initializing class ");
658     Debug.println(Debug.DEBUG, name);
659         
660     MethodInfo mi = getMethod("<clinit>()", false); // only local lookup
661

662     if (mi != null) {
663       // <2do> sync on class object here
664
// no args
665
th.executeMethod(mi);
666       // <2do> unsync
667
}
668   }
669   
670   /**
671    * Returns true if the given class is an instance of the class
672    * or interface specified.
673    */

674   public boolean instanceOf (String JavaDoc cname) {
675     cname = cname.replace('/', '.');
676     
677     // trivial case - ourself
678
if (name.equals(cname)) {
679       return true;
680     }
681     
682     // (recursive) parent
683
if ((superClass != null) && (superClass.instanceOf(cname))) {
684       return true;
685     }
686     
687     // direct interface
688
if (interfaces.contains(cname)) {
689       return true;
690     }
691     
692     // now it's getting more expensive - look for all interfaces
693
if (getAllInterfaces().contains(cname)) {
694       return true;
695     }
696     
697     // Ok, we give up
698
return false;
699   }
700   
701   /**
702    * clean up statics for another 'main' run
703    */

704   public static void reset () {
705     if (repository != null) {
706       repository.clear();
707     }
708     
709     loadedClasses = new Hashtable();
710     
711     classClassInfo = null;
712     objectClassInfo = null;
713     stringClassInfo = null;
714   }
715
716   /**
717    * provide a default path from where to load essential model classes
718    * (associated with native peers that JPF needs)
719    */

720   static String JavaDoc getDefaultBootClassPath () {
721     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
722     
723     // assuming we are in the JPF root dir, add build/env/jpf for explicit classes
724
sb.append("build");
725     sb.append(File.separatorChar);
726     sb.append("env");
727     sb.append(File.separatorChar);
728     sb.append("jpf");
729     
730     // but maybe this is a binary distrib, so add lib/env_jpf.jar
731
sb.append(File.pathSeparatorChar);
732     sb.append("lib");
733     sb.append(File.separatorChar);
734     sb.append("env_jpf.jar");
735
736     return sb.toString();
737   }
738   
739   /**
740    * this is for application specific classes that should not be seen by the host VM
741    */

742   static String JavaDoc getDefaultClassPath () {
743     return null;
744   }
745   
746   protected static SyntheticRepository createRepository (Config config) {
747     // <2do> pm - we have a collision with jpf.ClassPath (PCM)
748
// unfortunately, it's different enough to the JPF counterpart so that we
749
// have to keep both versions for now
750
org.apache.bcel.util.ClassPath cpath;
751     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(128);
752     String JavaDoc sep = System.getProperty("path.separator");
753     String JavaDoc v;
754
755     // this is where we get our essential model classes from (java.lang.Thread etc)
756
if ( (v = config.getExpandedString("vm.bootclasspath")) == null) {
757       v = getDefaultBootClassPath();
758     }
759     buf.append(v);
760     
761     // that's where the application specific environment should be loaded from
762
if ( (v = config.getExpandedString("vm.classpath")) == null) {
763       v = getDefaultClassPath();
764     }
765  
766     if (v != null) {
767       buf.append(sep);
768       buf.append(v);
769     }
770
771     // now we look into the system classpath (all stuff loaded from here is
772
// the same codebase that's also used by the host VM)
773
if (buf.length() > 0) {
774       buf.append(sep);
775     }
776     
777     buf.append(System.getProperty("java.class.path"));
778     
779     // finally, we load from the standard Java libraries
780
if (buf.length() > 0) {
781       buf.append(sep);
782     }
783     
784     buf.append(System.getProperty("sun.boot.class.path"));
785     
786     cpath = new org.apache.bcel.util.ClassPath(buf.toString());
787     
788     return SyntheticRepository.getInstance(cpath);
789   }
790   
791   protected static Set loadArrayInterfaces () {
792     Set interfaces;
793     
794     interfaces = new HashSet();
795     interfaces.add("java.lang.Cloneable");
796     interfaces.add("java.io.Serializable");
797     
798     return Collections.unmodifiableSet(interfaces);
799   }
800   
801   protected static Set loadBuiltinInterfaces (String JavaDoc type) {
802     return Collections.unmodifiableSet(new HashSet(0));
803   }
804   
805   /**
806    * Loads the interfaces of a class.
807    */

808   protected static Set loadInterfaces (JavaClass jc) {
809     Set interfaces;
810     String JavaDoc[] interfaceNames;
811     
812     interfaceNames = jc.getInterfaceNames();
813     interfaces = new HashSet();
814     
815     for (int i = 0, l = interfaceNames.length; i < l; i++) {
816       interfaces.add(interfaceNames[i]);
817     }
818     
819     return Collections.unmodifiableSet(interfaces);
820   }
821     
822   FieldInfo[] loadInstanceFields (JavaClass jc) {
823     Field[] fields = jc.getFields();
824     int i, j, n;
825     int off = (superClass != null) ? superClass.instanceDataSize : 0;
826     
827     for (i=0, n=0; i<fields.length; i++) {
828       if (!fields[i].isStatic()) n++;
829     }
830     
831     int idx = (superClass != null) ? superClass.nInstanceFields : 0;
832     FieldInfo[] ifa = new FieldInfo[n];
833     
834     for (i=0, j=0; i<fields.length; i++) {
835       Field f = fields[i];
836       if (!f.isStatic()) {
837         FieldInfo fi = FieldInfo.create(f, this, idx, off);
838         ifa[j++] = fi;
839         off += fi.getStorageSize();
840         idx++;
841         
842         if (attributor != null) {
843           fi.setAttributes( attributor.getFieldAttributes(jc, f));
844         }
845       }
846     }
847     
848     return ifa;
849   }
850   
851   int computeInstanceDataOffset () {
852     if (superClass == null) {
853       return 0;
854     } else {
855       return superClass.getInstanceDataSize();
856     }
857   }
858   
859   int getInstanceDataOffset () {
860     return instanceDataOffset;
861   }
862   
863   ClassInfo getClassBase (String JavaDoc clsBase) {
864     if ((clsBase == null) || (name.equals(clsBase))) return this;
865     
866     if (superClass != null) {
867       return superClass.getClassBase(clsBase);
868     }
869     
870     return null; // Eeek - somebody asked for a class that isn't in the base list
871
}
872   
873   int computeInstanceDataSize () {
874     int n = getDataSize( iFields);
875     
876     for (ClassInfo c=superClass; c!= null; c=c.superClass) {
877       n += c.getDataSize(c.iFields);
878     }
879     
880     return n;
881   }
882   
883   int getInstanceDataSize () {
884     return instanceDataSize;
885   }
886   
887   int getDataSize (FieldInfo[] fields) {
888     int n=0;
889     for (int i=0; i<fields.length; i++) {
890       n += fields[i].getStorageSize();
891     }
892     
893     return n;
894   }
895   
896   public int getNumberOfDeclaredInstanceFields () {
897     return iFields.length;
898   }
899   
900   FieldInfo getDeclaredInstanceField (int i) {
901     return iFields[i];
902   }
903   
904   public int getNumberOfInstanceFields () {
905     return nInstanceFields;
906   }
907   
908   FieldInfo getInstanceField (int i) {
909     int idx = i - (nInstanceFields - iFields.length);
910     if (idx >= 0) {
911       return ((idx < iFields.length) ? iFields[idx] : null);
912     } else {
913       return ((superClass != null) ? superClass.getInstanceField(i) : null);
914     }
915   }
916   
917   FieldInfo[] loadStaticFields (JavaClass jc) {
918     Field[] fields = jc.getFields();
919     int i, j, n;
920     int off = 0;
921     
922     for (i=0, n=0; i<fields.length; i++) {
923       if (fields[i].isStatic()) n++;
924     }
925     
926     FieldInfo[] sfa = new FieldInfo[n];
927     int idx = 0;
928     
929     for (i=0; i<fields.length; i++) {
930       Field f = fields[i];
931       if (f.isStatic()) {
932         FieldInfo fi = FieldInfo.create(f, this, idx, off);
933         sfa[idx] = fi;
934         idx++;
935         off += fi.getStorageSize();
936       }
937     }
938     
939     return sfa;
940   }
941   
942   int getStaticDataSize () {
943     return staticDataSize;
944   }
945   
946   int computeStaticDataSize () {
947     return getDataSize(sFields);
948   }
949   
950   public int getNumberOfStaticFields () {
951     return sFields.length;
952   }
953   
954   protected Source loadSource () {
955     return Source.getSource(sourceFileName);
956   }
957   
958   static boolean isBuiltinClass (String JavaDoc cname) {
959     char c = cname.charAt(0);
960     
961     // array class
962
if (c == '[') {
963       return true;
964     }
965     
966     // primitive type class
967
if (Character.isLowerCase(c)) {
968       if ("int".equals(cname) || "byte".equals(cname) ||
969           "boolean".equals(cname) || "double".equals(cname) ||
970           "long".equals(cname) || "char".equals(cname) ||
971           "short".equals(cname) || "float".equals(cname)) {
972         return true;
973       }
974     }
975     
976     return false;
977   }
978   
979   /**
980    * set the locations where we look up sources
981    */

982   static void setSourceRoots (Config config) {
983     String JavaDoc srcPath = config.getExpandedString("vm.sourcepath");
984     if (srcPath == null) { // our fallbacks, assuming we are in the JPF root dir
985
Source.addSourceRoot("examples");
986       Source.addSourceRoot("test");
987     } else {
988       StringTokenizer st = new StringTokenizer(srcPath, File.pathSeparator);
989       while (st.hasMoreTokens()) {
990         String JavaDoc sroot = st.nextToken();
991         
992         if ((sroot.length() > 0) && !sroot.endsWith(".jar")) {
993           Source.addSourceRoot(sroot);
994         }
995       }
996     }
997   }
998   
999   Set getAllInterfaces () {
1000    if (allInterfaces == null) {
1001      HashSet set = new HashSet();
1002      
1003      
1004      // load all own interfaces
1005
loadInterfaceRec(set, this);
1006      
1007      
1008      // all parent class interfaces
1009
loadInterfaceRec(set, superClass);
1010      
1011      allInterfaces = Collections.unmodifiableSet(set);
1012    }
1013    
1014    return allInterfaces;
1015  }
1016  
1017  ClassInfo getComponentClassInfo () {
1018    if (isArray()) {
1019      String JavaDoc cn = name.substring(1);
1020      
1021      if (cn.charAt(0) != '[') {
1022        cn = Types.getTypeName(cn);
1023      }
1024      
1025      ClassInfo cci = getClassInfo(cn);
1026      
1027      return cci;
1028    }
1029    
1030    return null;
1031  }
1032  
1033  /**
1034   * most definitely not a public method, but handy for the NativePeer
1035   */

1036  Map getDeclaredMethods () {
1037    return methods;
1038  }
1039  
1040  MethodInfo getFinalizer () {
1041    return finalizer;
1042  }
1043  
1044  int createClassObject (ThreadInfo th, int cref) {
1045    int objref;
1046    int cnref;
1047    DynamicArea da = JVM.getVM().getDynamicArea();
1048    
1049    objref = da.newObject(classClassInfo, th);
1050    cnref = da.newString(name, th);
1051    
1052    // we can't execute methods nicely for which we don't have caller bytecode
1053
// (would run into a (pc == null) assertion), so we have to bite the bullet
1054
// and init the java.lang.Class object explicitly. But that's probably Ok
1055
// since it is a very special beast, anyway
1056
ElementInfo e = da.get(objref);
1057    
1058    try {
1059      e.setReferenceField("name", cnref);
1060      
1061      // this is the StaticArea ElementInfo index of what we refer to
1062
e.setIntField("cref", cref);
1063    } catch (Exception JavaDoc x) {
1064      // if we don't have the right (JPF specific) java.lang.Class version,
1065
// we are screwed in terms of java.lang.Class usage
1066
if (classClassInfo == null) { // report it just once
1067
Debug.println(Debug.ERROR);
1068        Debug.println(Debug.ERROR,"FATAL ERROR: wrong java.lang.Class version");
1069        Debug.println(Debug.ERROR," you need to set 'vm.classpath'");
1070        Debug.println(Debug.ERROR," or start jpf from its root directory");
1071        Debug.println(Debug.ERROR);
1072        Debug.println(Debug.ERROR,
1073          " !! assertions or java.lang.Class usage will fail !!");
1074        Debug.println(Debug.ERROR);
1075      }
1076      
1077      return -1;
1078    }
1079    
1080    return objref;
1081  }
1082  
1083  /**
1084   * Creates the fields for a class. This gets called by the StaticArea
1085   * when a class is loaded.
1086   */

1087  Fields createStaticFields (StaticArea staticArea) {
1088    return new StaticFields(this);
1089  }
1090  
1091  void initializeStaticData (Fields f) {
1092    for (int i=0; i<sFields.length; i++) {
1093      FieldInfo fi = sFields[i];
1094      fi.initialize(f);
1095    }
1096  }
1097  
1098  void initializeInstanceData (Fields f) {
1099    // Note this is only used for field inits, and array elements are not fields!
1100
// Since Java has only limited element init requirements (either 0 or null),
1101
// we do this ad hoc in the ArrayFields ctor
1102

1103    // the order of inits should not matter, since this is only
1104
// for constant inits. In case of a "class X { int a=42; int b=a; ..}"
1105
// we have a explicit "GETFIELD a, PUTFIELD b" in the ctor
1106
for (int i=0; i<iFields.length; i++) {
1107      FieldInfo fi = iFields[i];
1108      fi.initialize(f);
1109    }
1110    if (superClass != null) {
1111      superClass.initializeInstanceData(f);
1112    }
1113  }
1114  
1115  Map loadArrayMethods () {
1116    return new HashMap(0);
1117  }
1118  
1119  Map loadBuiltinMethods (String JavaDoc type) {
1120    return new HashMap(0);
1121  }
1122  
1123  void loadInterfaceRec (Set set, ClassInfo ci) {
1124    if (ci != null) {
1125      Iterator it = ci.interfaces.iterator();
1126      
1127      while (it.hasNext()) {
1128        String JavaDoc iname = (String JavaDoc) it.next();
1129        set.add(iname);
1130        
1131        ci = getClassInfo(iname);
1132        loadInterfaceRec(set, ci);
1133      }
1134    }
1135  }
1136  
1137  /**
1138   * this is a optimization to work around the BCEL strangeness that some
1139   * insn info (types etc.) are only accessible with modifiable ConstPools
1140   * (the ConstantPoolGen, which is costly to create), and some others
1141   * (toString) are only provided via ConstPools. It's way to expensive
1142   * to create this always on the fly, for each relevant insn, so we cache it
1143   * here
1144   */

1145  static ConstantPool cpCache;
1146  static ConstantPoolGen cpgCache;
1147  
1148  public static ConstantPoolGen getConstantPoolGen (ConstantPool cp) {
1149    if (cp != cpCache) {
1150      cpCache = cp;
1151      cpgCache = new ConstantPoolGen(cp);
1152    }
1153    
1154    return cpgCache;
1155  }
1156  
1157  /** avoid memory leaks */
1158  static void resetCPCache () {
1159    cpCache = null;
1160    cpgCache = null;
1161  }
1162  
1163  Map loadMethods (JavaClass jc) {
1164    Method[] ms = jc.getMethods();
1165    HashMap map = new HashMap(ms.length);
1166    
1167    for (int i = 0; i < ms.length; i++) {
1168      MethodInfo mi = MethodInfo.newInstance(ms[i], this);
1169      String JavaDoc id = mi.getUniqueName();
1170      map.put(id, mi);
1171      
1172      if (attributor != null) {
1173        mi.setAtomic( attributor.isMethodAtomic(jc, ms[i], id));
1174        mi.setSchedulingRelevance( attributor.getSchedulingRelevance( jc, ms[i], id));
1175      }
1176    }
1177    
1178    resetCPCache(); // no memory leaks
1179

1180    return map;
1181  }
1182  
1183  ClassInfo loadSuperClass (JavaClass jc) {
1184    if (this == objectClassInfo) {
1185      return null;
1186    } else {
1187      String JavaDoc superName = jc.getSuperclassName();
1188      
1189      return getClassInfo(superName);
1190    }
1191  }
1192  
1193  int loadElementInfoAttrs (JavaClass jc) {
1194    // we use the atomicizer for it because the only attribute for now is the
1195
// immutability, and it is used to determine if a field insn should be
1196
// a step boundary. Otherwise it's a bit artificial, but we don't want
1197
// to intro another load time class attributor for now
1198
if (attributor != null) {
1199      return attributor.getObjectAttributes(jc);
1200    }
1201    
1202    return 0;
1203  }
1204  
1205  
1206  private MethodInfo getFinalizer0 () {
1207    MethodInfo mi = getMethod("finalize()", true);
1208    
1209    // we are only interested in non-empty method bodies, Object.finalize()
1210
// is a dummy
1211
if ((mi != null) && (mi.getClassInfo() != objectClassInfo)) {
1212      return mi;
1213    }
1214    
1215    return null;
1216  }
1217  
1218  private boolean isWeakReference0 () {
1219    for (ClassInfo ci = this; ci != objectClassInfo; ci = ci.superClass) {
1220      if (ci == weakRefClassInfo) {
1221        return true;
1222      }
1223    }
1224    
1225    return false;
1226  }
1227}
1228
1229
1230
Popular Tags