00001 package gov.nasa.arc.ase.jpf.jvm;
00002
00003 import de.fub.bytecode.*;
00004 import de.fub.bytecode.classfile.*;
00005 import de.fub.bytecode.generic.*;
00006 import gov.nasa.arc.ase.jpf.*;
00007 import gov.nasa.arc.ase.jpf.jvm.reflection.Reflection;
00008 import gov.nasa.arc.ase.util.Debug;
00009 import java.io.*;
00010 import java.util.*;
00011
00012 import gov.nasa.arc.ase.jpf.jvm.runtime.*;
00013
00014
00015 public class ClassInfo {
00016
00017 private JavaClass classData;
00018
00019 private ConstantPoolGen classConstantPool;
00020
00021 private Hashtable methodList = new Hashtable();
00022
00023 private Field[] dynamicFields;
00024
00025 private Field[] staticFields;
00026
00027 private SafeBlocks safeBlocks;
00028
00029
00030
00031 private ClassInfo superClass;
00032
00033 private static String[] reflectionPath = {
00034 "gov.nasa.arc.ase.jpf.jvm.reflection", ""
00035 };
00036
00037 Hashtable fieldNames = new Hashtable();
00038
00039 Reflection reflection = null;
00040
00041 private static String[] classPath = null;
00042
00043
00044 public ClassInfo(JavaClass cd) {
00045
00046
00047 classData = cd;
00048
00049 if(Engine.options.po_reduction)
00050 loadSafeBlocks(cd);
00051 else
00052 safeBlocks = null;
00053
00054 classConstantPool = new ConstantPoolGen(cd.getConstantPool());
00055
00056
00057 int nsfields = 0;
00058 int ndfields = 0;
00059 Field[] fields = classData.getFields();
00060 for(int i = 0, l = fields.length; i < l; i++)
00061 if(fields[i].isStatic())
00062 nsfields++;
00063 else
00064 ndfields++;
00065
00066 JavaClass jc = JPFVM.getJPFVM().loadClassData(classData.getSuperclassName());
00067 while(!jc.getClassName().equals("java.lang.Object")) {
00068 fields = jc.getFields();
00069 for(int i = 0, l = fields.length; i < l; i++)
00070 if(!fields[i].isStatic())
00071 ndfields++;
00072 jc = JPFVM.getJPFVM().loadClassData(jc.getSuperclassName());
00073 }
00074
00075 staticFields = new Field[nsfields];
00076 dynamicFields = new Field[ndfields];
00077
00078 int sfc = 0;
00079 int dfc = 0;
00080
00081 fields = classData.getFields();
00082 for(int i = 0, l = fields.length; i < l; i++)
00083 if(fields[i].isStatic())
00084 staticFields[sfc++] = fields[i];
00085 else
00086 dynamicFields[dfc++] = fields[i];
00087
00088 jc = JPFVM.getJPFVM().loadClassData(classData.getSuperclassName());
00089 while(!jc.getClassName().equals("java.lang.Object")) {
00090 fields = jc.getFields();
00091 for(int i = 0, l = fields.length; i < l; i++)
00092 if(!fields[i].isStatic())
00093 dynamicFields[dfc++] = fields[i];
00094 jc = JPFVM.getJPFVM().loadClassData(jc.getSuperclassName());
00095 }
00096
00097
00098 Method[] methods = cd.getMethods();
00099 for(int i = 0, s = methods.length; i < s; i++) {
00100 Method m = methods[i];
00101 MethodInfo mi = new MethodInfo(m, this, classConstantPool);
00102 methodList.put(mi.getMethodName()+m.getSignature(), mi);
00103 }
00104
00105 String superName = cd.getSuperclassName();
00106
00107 if (cd.getClassName().equals("java.lang.Object")) {
00108
00109
00110
00111 superClass = null;
00112 } else {
00113
00114
00115
00116
00117 superClass = JPFVM.getJPFVM().getClass(superName);
00118 }
00119
00120 initFields();
00121
00122 setReflection(cd.getClassName());
00123 }
00124 public long callMethod(SystemState ss, KernelState ks, ThreadInfo th, String name, int[] args) {
00125 Reflection r = (Reflection)reflection.clone();
00126 r.setState(ss, ks, th);
00127 r.setObjectReference(args[0]);
00128
00129 return r.callMethod(name, args);
00130 }
00131 public long callStaticMethod(SystemState ss, KernelState ks, ThreadInfo th, String name, int[] args) {
00132 reflection.setState(ss, ks, th);
00133
00134 return reflection.callStaticMethod(name, args);
00135 }
00136 public Fields createFields() {
00137 Field[] fs = dynamicFields;
00138 Fields f = new Fields(this, fs.length);
00139 for(int i = 0, l = fs.length; i < l; i++) {
00140 f.setValue(i, Types.newValue(fs[i].getSignature()));
00141
00142 if(Types.isReference(fs[i].getSignature()))
00143 f.setValueRef(i);
00144
00145 }
00146
00147 return f;
00148 }
00149 public Fields createStaticFields() {
00150 Field[] fs = staticFields;
00151 Fields f = new Fields(this, fs.length);
00152 for(int i = 0, l = fs.length; i < l; i++) {
00153 f.setValue(i, Types.newValue(fs[i].getSignature()));
00154
00155 if(Types.isReference(fs[i].getSignature()))
00156 f.setValueRef(i);
00157
00158 }
00159
00160 return f;
00161 }
00162
00163 private void DEPEND_ExecuteMainMethod(ThreadInfo th){
00164 if (Depend.on()){
00165 Depend.addMain(th);
00166 }
00167 }
00168
00169
00170
00171 public ThreadInfo executeMain(KernelState ks, int classref) {
00172 ThreadInfo th = new ThreadInfo();
00173 ks.newThread(th);
00174
00175 th.setStatus(STATUS.RUNNING);
00176 th.setClassInfo(this);
00177 th.setReference(new ClassRef(classref));
00178 th.newFrame(getMethodInfo("main([Ljava/lang/String;)V"));
00179
00180
00181 th.setLocalVariable(0, (int)Types.newValue("[Ljava/lang/String;"));
00182
00183 th.setLocalVariableRef(0);
00184
00185
00186
00187
00188
00189
00190
00191 DEPEND_ExecuteMainMethod(th);
00192
00193
00194 return th;
00195 }
00196 public InstructionHandle executeMethod(SystemState ss, KernelState ks, ThreadInfo th, String name) {
00197 MethodInfo mi = getMethodInfo(name);
00198 boolean atomic = TransitionResult.isAtomic();
00199 String cn = classData.getClassName();
00200
00201 if(cn.startsWith("java.lang.") || cn.startsWith("java.util."))
00202 atomic = true;
00203
00204 Reflection r = (Reflection)reflection.clone();
00205 r.setState(ss, ks, th);
00206 r.setObjectReference(th.getCalleeThis(mi.getArgumentSize()));
00207
00208 th.createMethodStackFrame(mi);
00209
00210 return r.executeMethod(mi, atomic);
00211 }
00212 public InstructionHandle executeStaticMethod(SystemState ss, KernelState ks, ThreadInfo th, String name) {
00213 MethodInfo mi = getMethodInfo(name);
00214 boolean atomic = TransitionResult.isAtomic();
00215 String cn = classData.getClassName();
00216
00217 if(cn.startsWith("java.lang.") || cn.startsWith("java.util."))
00218 atomic = true;
00219
00220 if(name.equals("<clinit>()V") && VirtualMachine.options.atomic_init)
00221 atomic = true;
00222
00223 reflection.setState(ss, ks, th);
00224
00225 th.createMethodStackFrame(mi);
00226
00227 return reflection.executeStaticMethod(mi, atomic);
00228 }
00229 public JavaClass getClassData() {
00230 return classData;
00231 }
00232 public String getClassName() {
00233 return classData.getClassName();
00234 }
00235 public ConstantPoolGen getCPG() {
00236 return classConstantPool;
00237 }
00238 public Field[] getDynamicFields() {
00239 return dynamicFields;
00240 }
00241 public String getFieldName(int index) {
00242 return (String)fieldNames.get(new Integer(index));
00243 }
00244 public int getFieldType(int index) {
00245 return Type.getType(dynamicFields[index].getSignature()).getType();
00246 }
00247 public int getFieldType(String fname) {
00248 int index = ((Integer)fieldNames.get(fname)).intValue();
00249
00250 return Type.getType(dynamicFields[index].getSignature()).getType();
00251 }
00252 public MethodInfo getMethodInfo(String name) {
00253 MethodInfo mi = (MethodInfo) methodList.get(name);
00254 if (mi == null) {
00255 if (name.equals("<clinit>()V"))
00256 return null;
00257
00258
00259
00260
00261 if (superClass == null) {
00262 Debug.println(Debug.ERROR, "Method not found: " + name);
00263 System.exit(0);
00264 }
00265 return superClass.getMethodInfo(name);
00266 }
00267 else
00268 return mi;
00269 }
00270 public Field[] getStaticFields() {
00271 return staticFields;
00272 }
00273 public int getStaticFieldType(int index) {
00274 return Type.getType(staticFields[index].getSignature()).getType();
00275 }
00276 public int getStaticFieldType(String fname) {
00277 int index = ((Integer)fieldNames.get(fname)).intValue();
00278
00279 return Type.getType(staticFields[index].getSignature()).getType();
00280 }
00281 public ClassInfo getSuperClassInfo() {
00282 return superClass;
00283 }
00284 private void initFields() {
00285 Field[] fs = dynamicFields;
00286 for(int i = 0, s = fs.length; i < s; i++)
00287 fieldNames.put(fs[i].getName(), new Integer(i));
00288
00289 fs = getStaticFields();
00290 for(int i = 0, s = fs.length; i < s; i++)
00291 fieldNames.put(fs[i].getName(), new Integer(i));
00292 }
00293
00294 public InstructionHandle initialize(SystemState ss, KernelState ks, ThreadInfo th) {
00295 if(methodList.get("<clinit>()V") == null) return th.getPC();
00296
00297 return executeStaticMethod(ss, ks, th, "<clinit>()V");
00298 }
00299 public boolean isMethodDeterministic(SystemState ss, KernelState ks, ThreadInfo th, String name) {
00300 MethodInfo mi = getMethodInfo(name);
00301
00302 Reflection r = (Reflection)reflection.clone();
00303 r.setState(ss, ks, th);
00304 r.setObjectReference(th.getCalleeThis(mi.getArgumentSize()));
00305
00306 return r.isMethodDeterministic(mi);
00307 }
00308 public boolean isMethodExecutable(SystemState ss, KernelState ks, ThreadInfo th, String name) {
00309 MethodInfo mi = getMethodInfo(name);
00310
00311 Reflection r = (Reflection)reflection.clone();
00312 r.setState(ss, ks, th);
00313 r.setObjectReference(th.getCalleeThis(mi.getArgumentSize()));
00314
00315 int stacksize = th.size();
00316 return r.isMethodExecutable(mi);
00317 }
00318 public boolean isSafe(int line) {
00319 if (safeBlocks == null)
00320 return false;
00321 else
00322 return safeBlocks.isSafe(line);
00323 }
00324 public boolean isStaticMethodDeterministic(SystemState ss, KernelState ks, ThreadInfo th, String name) {
00325 MethodInfo mi = getMethodInfo(name);
00326
00327 reflection.setState(ss, ks, th);
00328
00329 return reflection.isStaticMethodDeterministic(mi);
00330 }
00331 public boolean isStaticMethodExecutable(SystemState ss, KernelState ks, ThreadInfo th, String name) {
00332 MethodInfo mi = getMethodInfo(name);
00333
00334 reflection.setState(ss, ks, th);
00335
00336 return reflection.isStaticMethodExecutable(mi);
00337 }
00338 public boolean isThread() {
00339 ClassInfo ci = this;
00340
00341 while (ci != null) {
00342 if (ci.getClassName().equals("java.lang.Thread"))
00343 return true;
00344 ci = ci.superClass;
00345 }
00346
00347 return false;
00348 }
00349 private void loadSafeBlocks(JavaClass cd) {
00350 if(classPath == null) setClassPath();
00351
00352
00353 String name = cd.getClassName().replace('.', '/');
00354
00355 for(int i = 0; i < classPath.length; i++)
00356 try {
00357 String filename = classPath[i] + "/" + name + ".safe";
00358 BufferedReader in = new BufferedReader(new FileReader(filename));
00359 Debug.println(Debug.WARNING, "Loading " + filename);
00360 safeBlocks = new SafeBlocks(in);
00361
00362 return;
00363 } catch (FileNotFoundException e) {
00364 }
00365
00366 safeBlocks = null;
00367 }
00368 public String reflectionClassName(String name) {
00369 int index = 0;
00370 int last = 0;
00371 StringBuffer sb = new StringBuffer();
00372
00373 while((index = name.indexOf(".", last)) != -1) {
00374 sb.append(Character.toUpperCase(name.charAt(last)));
00375 sb.append(name.substring(last + 1, index));
00376 last = index + 1;
00377 }
00378 sb.append(name.substring(last));
00379
00380 return sb.toString();
00381 }
00382 private static void setClassPath() {
00383 StringTokenizer st = new StringTokenizer(System.getProperty("java.class.path"), ":");
00384 classPath = new String[st.countTokens()];
00385 for(int i = 0; st.hasMoreTokens(); i++)
00386 classPath[i] = st.nextToken();
00387 }
00388 private void setReflection(String name) {
00389 int l = reflectionPath.length;
00390
00391 for(int i = 0; i < l && reflection == null; i++) {
00392 String cn;
00393
00394 if(reflectionPath[i].equals(""))
00395 cn = name + "Reflection";
00396 else
00397 cn = reflectionPath[i] + "." + name + "Reflection";
00398 try {
00399 Class clazz = Class.forName(cn);
00400 reflection = (Reflection)clazz.newInstance();
00401 Debug.println(Debug.WARNING, "Loading class " + cn);
00402 } catch(InstantiationException e) {
00403 Debug.println(Debug.ERROR, "Can't instantiate " + cn);
00404 System.exit(1);
00405 } catch(IllegalAccessException e) {
00406 Debug.println(Debug.ERROR, "Can't instantiate " + cn);
00407 System.exit(1);
00408 } catch(ClassNotFoundException e) {
00409 }
00410 }
00411
00412 for(int i = 0; i < l && reflection == null; i++) {
00413 String cn;
00414 if(reflectionPath[i].equals(""))
00415 cn = reflectionClassName(name) + "Reflection";
00416 else
00417 cn = reflectionPath[i] + "." + reflectionClassName(name) + "Reflection";
00418 try {
00419 Class clazz = Class.forName(cn);
00420 reflection = (Reflection)clazz.newInstance();
00421 Debug.println(Debug.WARNING, "Loading class " + cn);
00422 } catch(InstantiationException e) {
00423 Debug.println(Debug.ERROR, "Can't instantiate " + cn);
00424 System.exit(1);
00425 } catch(IllegalAccessException e) {
00426 Debug.println(Debug.ERROR, "Can't instantiate " + cn);
00427 System.exit(1);
00428 } catch(ClassNotFoundException e) {
00429 }
00430 }
00431
00432 if(reflection == null)
00433 reflection = new Reflection();
00434
00435 reflection.setClassInfo(this);
00436 }
00437 }