Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Slicer.java

00001 package edu.ksu.cis.bandera.pdgslicer;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   Hongjun Zheng (zheng@cis.ksu.edu)      *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the preceding statement.                           *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this toolkit; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 
00036 import edu.ksu.cis.bandera.annotation.*;
00037 import edu.ksu.cis.bandera.jjjc.CompilationManager;
00038 import edu.ksu.cis.bandera.pdgslicer.datastructure.*;
00039 import ca.mcgill.sable.util.*;
00040 import ca.mcgill.sable.soot.*;
00041 import ca.mcgill.sable.soot.jimple.*;
00042 import java.io.*;
00043 import java.util.Vector;
00044 import java.util.Hashtable;
00045 /**
00046  * The entry class of the slicer. This class shows the program structure of the
00047  * slicer:
00048 * <ul>
00049    * <li> Collect some basic information of program;
00050    * <li> Determine slicing criterion;
00051    * <li> Build program dependency graph for each method in the program;
00052    * <li> Slice each method in the program;
00053    * <li> Construct residual program;
00054    * <li> Dump residual program.
00055    * </ul>
00056 * Usage of this class:
00057 * <p>
00058 * <code>
00059 * Slicer slicer = new Slicer(sootClassArray, sliceCriterion, annotationManager);
00060 * <br>slicer.run();
00061 * <br> ... ...
00062 * <br>SootClass sliceResult[] = slicer.result();
00063 * </code>
00064  */
00065 
00066 public class Slicer {
00067     public static boolean Turn_On_BOFA = true;
00068     public static edu.ksu.cis.bandera.bofa.Analysis BOFA_Analysis = null;
00069     private PostProcessOnAnnotation postProcessOnAnnotation = null;
00070     public static AnnotationManager annManagerForSlicer = null;
00071     /**
00072     * a set of reachable {@link SootMethod SootMethod}.
00073     */
00074     public static Set reachableMethods;
00075     /**
00076     * a set of unreachable {@link SootClass SootClass}.
00077     */
00078     public static Set unreachableClasses;
00079     /** 
00080     * an array for residual classes.
00081     */
00082     private SootClass residualSootClassArray[];
00083     /**
00084     * a list of {@link ClassInfo ClassInfo}.
00085     */
00086     private List classInfoList = new ArrayList();
00087     /**
00088     * a map from {@link SootMethod SootMethod} to
00089     * {@link MethodInfo MethodInfo}, for all methods
00090     * of all involved classes.
00091     */
00092     public static Map sootMethodInfoMap = null;
00093     public static SliceTraceNode sliceTraceRoot;
00094     /**
00095     * a set of {@link SliceTraceNode SliceTraceNode}.
00096     */
00097     public static Set allSliceTraceNodes;
00098     /**
00099     * a map from {@link SootClass SootClass} to a {@link Set Set} of
00100     * {@link SootClass SootClass}, representing that one interface
00101     * is implemented by a set of classes, or one abstract class is
00102     * implemented(extended) by a set of classes.
00103     */
00104     static Map interfaceImplementedByMap = null;
00105     /**
00106     * a {@link Set Set} of {@link MethodInfo MethodInfo}
00107     * such that the corresponding method has slicing criterion.
00108     */
00109     static Set originalMethods = null;
00110     /**
00111     * number of involved classes.
00112     */
00113     static int classNum;
00114     static SootClass relevantClassArray[];
00115     private AnnotationManager cfanns;
00116     /**
00117     * slicing criterion --- a vector of {@link SliceInterest SliceInterest}.
00118     */ 
00119     private Vector sliceInterestVec;
00120 /**
00121  * The constructor for the case that there is <b>NO</b> slicing criterion specified
00122  * by users.
00123  * <p>
00124  * @param relClasses an array of {@link SootClass SootClass} which will be analysed and sliced
00125  * by the slicer.
00126  * @param annoManager annotation manager.
00127  */
00128 public Slicer(SootClass relClasses[], AnnotationManager annoManager) {
00129     SlicingMethod.criterionChanged = false;
00130     //SlicingMethod.originalMdsFromReadyCallSite = new ArraySet();
00131     SlicingMethod.alreadyGenCritByReadyCallSite = new ArraySet();
00132     SlicingMethod.alreadyGenerateCriterionForExits = new ArraySet();
00133     MethodCallAnalysis.directReadyForWaitCallSites = new ArraySet();
00134     InfoAnalysis.nativeMdSig = new ArraySet();
00135     annManagerForSlicer = annoManager;
00136     relevantClassArray = relClasses;
00137     cfanns = annoManager;
00138     classNum = relevantClassArray.length;
00139     originalMethods = new ArraySet();
00140     interfaceImplementedByMap = new HashMap();
00141     sootMethodInfoMap = new HashMap();
00142     sliceTraceRoot = new SliceTraceNode();
00143     allSliceTraceNodes = new ArraySet();
00144     reachableMethods = new ArraySet();
00145     unreachableClasses = new ArraySet();
00146     sliceInterestVec = new Vector();
00147 
00148 }
00149 /**
00150  * The constructor for the case that there is slicing criterion specified
00151  * by users.
00152  * <p>
00153  * @param relClasses an array of {@link SootClass SootClass} which will be analysed and sliced
00154  * by the slicer.
00155  * @param interestVector slicing criterion.
00156  * A {@link Vector} of {@link SliceInterest SliceInterest}.
00157  * @param annoManager annotation manager.
00158  */
00159 public Slicer(SootClass relClasses[], Vector interestVector, AnnotationManager annoManager) {
00160     this(relClasses, annoManager);
00161     sliceInterestVec = interestVector;
00162 }
00163 /**
00164 * Build up {@link #classInfoList classInfoList} 
00165 * and {@link #interfaceImplementedByMap interfaceImplementedByMap} 
00166 * for each class.
00167 * <br> Set value for {@link Slicer#classNum Slicer.classNum}.
00168 */
00169 private void basicInformation() {
00170     for (int i = 0; i < relevantClassArray.length; i++) {
00171         SootClass sootClass = relevantClassArray[i];
00172         int modifiers = sootClass.getModifiers();
00173         if (Modifier.isInterface(modifiers)) {
00174             System.out.println("Class " + sootClass.getName() + " is an interface");
00175             continue;
00176         }
00177         if (sootClass.getMethods().size() == 0) {
00178             System.out.println("There is no method in class " + sootClass.getName());
00179             continue;
00180         }
00181         InfoAnalysis information = new InfoAnalysis(sootClass);
00182         ClassInfo classInfo = new ClassInfo();
00183         classInfo.sootClass = sootClass;
00184         classInfo.methodsInfoList = information.getMethodsInfoList();
00185         classInfoList.add(classInfo);
00186         if (information.getMethodsInfoList().isEmpty()) {
00187             //if there is no static field
00188 
00189             if (!haveStaticFields(sootClass))
00190                 Slicer.unreachableClasses.add(sootClass);
00191             else
00192                 
00193                 //add clinit method into reachableMethods if any
00194                 {
00195                 if (sootClass.declaresMethod("<clinit>"))
00196                     Slicer.reachableMethods.add(sootClass.getMethod("<clinit>"));
00197             }
00198         } else
00199             if (sootClass.declaresMethod("<clinit>"))
00200                 Slicer.reachableMethods.add(sootClass.getMethod("<clinit>"));
00201     }
00202     //Slicer.classNum = classInfoList.size();
00203 }
00204 /**
00205  * Insert the method's description here.
00206  * Creation date: (00-10-21 1:16:30)
00207  */
00208 private void buildInterfaceAndSuperClassMap() {
00209     for (int i = 0; i < relevantClassArray.length; i++) {
00210         SootClass sootClass = relevantClassArray[i];
00211         int modifiers = sootClass.getModifiers();
00212         if (Modifier.isInterface(modifiers)) {
00213             System.out.println("Class " + sootClass.getName() + " is an interface");
00214             continue;
00215         }
00216         if (sootClass.getMethods().size() == 0) {
00217             System.out.println("There is no method in class " + sootClass.getName());
00218             continue;
00219         }
00220         for (Iterator inIt = sootClass.getInterfaces().iterator(); inIt.hasNext();) {
00221             SootClass implementedClass = (SootClass) inIt.next();
00222             if (interfaceImplementedByMap.containsKey(implementedClass)) {
00223                 ((Set) interfaceImplementedByMap.get(implementedClass)).add(sootClass);
00224             } else {
00225                 Set impSet = new ArraySet();
00226                 impSet.add(sootClass);
00227                 interfaceImplementedByMap.put(implementedClass, impSet);
00228             }
00229         }
00230         //Process abstract class and its subclass
00231         //added on 10/6/2000
00232         if (sootClass.hasSuperClass()) {
00233             try {
00234                 SootClass superClass = sootClass.getSuperClass();
00235                 //int modifier = superClass.getModifiers();
00236                 //if (Modifier.isAbstract(modifier)) {
00237                 //if (!superClass.getName().equals("java.lang.Object")) {
00238                 if (!isObjectClass(superClass)) {
00239                     if (interfaceImplementedByMap.containsKey(superClass)) {
00240                         ((Set) interfaceImplementedByMap.get(superClass)).add(sootClass);
00241                     } else {
00242                         Set impSet = new ArraySet();
00243                         impSet.add(sootClass);
00244                         interfaceImplementedByMap.put(superClass, impSet);
00245                     }
00246                 }
00247             } catch (NoSuperClassException e) {
00248             }
00249         }
00250     }
00251 }
00252 /**
00253 * Build PDG without slicing criterion:
00254 * {@link #basicInformation() basicInformation()},
00255 * {@link #moreInformation() moreInformation()}. 
00256 * <br> This method is only used by the browser of PDG.
00257 */
00258 public void buildPDG() {
00259     Slicer.Turn_On_BOFA = true;
00260     if (Slicer.Turn_On_BOFA) {
00261         edu.ksu.cis.bandera.bofa.BOFA.reset();
00262         edu.ksu.cis.bandera.bofa.BOFA.analyze();
00263         BOFA_Analysis = edu.ksu.cis.bandera.bofa.Analysis.init();
00264     }
00265     buildInterfaceAndSuperClassMap();
00266     collectReachableMethods();
00267     basicInformation();
00268     collectOriginalMethods();
00269     moreInformation();
00270 }
00271 /**
00272 * Collect all methods with slicing criterion into
00273 * {@link #originalMethods originalMethods}.
00274 */
00275 private void collectOriginalMethods() {
00276     for (Iterator sootMdIt = Slicer.sootMethodInfoMap.keySet().iterator(); sootMdIt.hasNext();)
00277     {
00278         SootMethod sootMethod = (SootMethod) sootMdIt.next();
00279         MethodInfo mdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(sootMethod);
00280         if (mdInfo.sCriterion == null) continue;
00281         originalMethods.add(mdInfo);
00282     }
00283 }
00284 /**
00285  * Insert the method's description here.
00286  * Creation date: (00-10-21 0:03:47)
00287  */
00288 private void collectReachableMethods() {
00289     Set startingMethods = getStartingMethods();
00290     //starting methods include all methods with slicing criterion
00291     //all methods such like "main" and "run";
00292     reachableMethods.addAll(startingMethods);
00293     Set visitedMds = new ArraySet();
00294     LinkedList workList = new LinkedList();
00295     workList.addAll(startingMethods);
00296     while (!workList.isEmpty()) {
00297         SootMethod sm = (SootMethod) workList.removeFirst();
00298         visitedMds.add(sm);
00299         int scModifiers = sm.getDeclaringClass().getModifiers();
00300         int smModifiers = sm.getModifiers();
00301         if (Modifier.isInterface(scModifiers) || Modifier.isAbstract(smModifiers))
00302             continue;
00303         //process sm
00304         JimpleBody jimpleBody = null;
00305         try {
00306             jimpleBody = (JimpleBody) sm.getBody(Jimple.v());
00307         } catch (RuntimeException re) {
00308             //this means the method is from jar files
00309             //re.printStackTrace();
00310             System.out.println("There is no method body for method " + sm);
00311             continue;
00312         }
00313         StmtList stmtList = jimpleBody.getStmtList();
00314         for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00315             Stmt stmt = (Stmt) stmtIt.next();
00316             Set invokedMds = getInvokedMdsFrom(stmt,sm);
00317             reachableMethods.addAll(invokedMds);
00318             for (Iterator mdIt = invokedMds.iterator(); mdIt.hasNext();) {
00319                 SootMethod invokedMd = (SootMethod) mdIt.next();
00320                 if (!visitedMds.contains(invokedMd) && !workList.contains(invokedMd))
00321                     workList.addLast(invokedMd);
00322             }
00323         }
00324         SootClass sootClass = sm.getDeclaringClass();
00325         if (sootClass.declaresMethod("<clinit>")) {
00326             SootMethod classInitMd = sootClass.getMethod("<clinit>");
00327             if (!visitedMds.contains(classInitMd) && !workList.contains(classInitMd))
00328                 workList.addLast(classInitMd);
00329             if (!reachableMethods.contains(classInitMd))
00330                 reachableMethods.add(classInitMd);
00331         }
00332     }
00333 }
00334 /**
00335  * Dump a set of soot classes into files with provided extension.
00336  * <br> This method is only for internal debugging.
00337  * <p>
00338  * @param dumpedClasses an array of soot classes being dumped.
00339  * @param extension a string for file extension.
00340  */
00341 private void dumpJimpleCode(SootClass dumpedClasses[], String extension) {
00342     StoredBody bd = new StoredBody(Jimple.v());
00343     String outputPath = ".";
00344     for (int i = 0; i < dumpedClasses.length; i++) {
00345         SootClass sc = dumpedClasses[i];
00346         String className = sc.getName();
00347         try {
00348             File jimpFile = new File(outputPath + File.separator + className + extension);
00349             FileOutputStream jimpOut = new FileOutputStream(jimpFile);
00350             sc.printTo(bd, new PrintWriter(jimpOut, true));
00351         } catch (IOException ex) {
00352             throw new RuntimeException("Could not dump jimple file (" + className + ")");
00353         }
00354     }
00355 }
00356 /**
00357  * Insert the method's description here.
00358  * Creation date: (00-10-21 1:48:49)
00359  * @return ca.mcgill.sable.util.Set
00360  * @param invokeExpr ca.mcgill.sable.soot.jimple.InvokeExpr
00361  */
00362 private Set getInvokedMdsFrom(InvokeExpr invokeExpr, SootMethod enclosingMethod) {
00363     Set invokedMds = new ArraySet();
00364     if (Slicer.Turn_On_BOFA && (invokeExpr instanceof NonStaticInvokeExpr)) {
00365         SootMethod invokedMethod = invokeExpr.getMethod();
00366         if (invokedMethod.getSignature().startsWith("java.") || invokedMethod.getSignature().startsWith("javax."))
00367             return invokedMds;
00368         Collection classVariants = Slicer.BOFA_Analysis.invokeExprResolution((NonStaticInvokeExpr) invokeExpr, enclosingMethod);
00369         for (Iterator classIt = classVariants.iterator(); classIt.hasNext();) {
00370             SootClass classVariant = (SootClass) classIt.next();
00371             invokedMds.add(classVariant.getMethod(invokedMethod.getName(), invokedMethod.getParameterTypes(), invokedMethod.getReturnType()));
00372         }
00373     } else {
00374         SootMethod invokedMd = invokeExpr.getMethod();
00375         if (invokedMd.getSignature().startsWith("java.") || invokedMd.getSignature().startsWith("javax."))
00376             return invokedMds;
00377         SootClass invokedClass = invokedMd.getDeclaringClass();
00378         invokedMds.add(invokedMd);
00379         if (interfaceImplementedByMap.containsKey(invokedClass)) {
00380             List paraTypes = invokedMd.getParameterTypes();
00381             Type returnType = invokedMd.getReturnType();
00382             String mdName = invokedMd.getName();
00383             Set subClasses = (Set) interfaceImplementedByMap.get(invokedClass);
00384             for (Iterator subIt = subClasses.iterator(); subIt.hasNext();) {
00385                 SootClass subClass = (SootClass) subIt.next();
00386                 if (subClass.declaresMethod(mdName, paraTypes, returnType))
00387                     invokedMds.add(subClass.getMethod(mdName, paraTypes, returnType));
00388             }
00389         }
00390     }
00391     return invokedMds;
00392 }
00393 /**
00394  * Insert the method's description here.
00395  * Creation date: (00-10-21 1:38:48)
00396  * @return ca.mcgill.sable.util.Set
00397  * @param stmt ca.mcgill.sable.soot.jimple.Stmt
00398  */
00399 private Set getInvokedMdsFrom(Stmt stmt, SootMethod enclosingMethod) {
00400     Set invokedMds = new ArraySet();
00401     if (SlicingMethod.isBanderaInvoke(stmt)) {
00402     } else
00403         if (stmt instanceof InvokeStmt) {
00404             InvokeExpr invokeExpr = (InvokeExpr) ((InvokeStmt) stmt).getInvokeExpr();
00405             Set invokedMdsByStmt = getInvokedMdsFrom(invokeExpr, enclosingMethod);
00406             invokedMds.addAll(invokedMdsByStmt);
00407         } else {
00408             List valueBoxes = stmt.getUseAndDefBoxes();
00409             for (Iterator vIt = valueBoxes.iterator(); vIt.hasNext();) {
00410                 ValueBox vbox = (ValueBox) vIt.next();
00411                 Value value = vbox.getValue();
00412                 if (value instanceof InvokeExpr) {
00413                     Set invokedMdsByValue = getInvokedMdsFrom((InvokeExpr) value, enclosingMethod);
00414                     invokedMds.addAll(invokedMdsByValue);
00415                 }
00416             }
00417         }
00418     return invokedMds;
00419 }
00420 /**
00421  * Insert the method's description here.
00422  * Creation date: (00-12-6 16:17:08)
00423  * @return edu.ksu.cis.bandera.pdgslicer.PostProcessOnAnnotation
00424  */
00425 public PostProcessOnAnnotation getPostProcessOnAnnotation() {
00426     return postProcessOnAnnotation;
00427 }
00428 /**
00429  * Insert the method's description here.
00430  * Creation date: (00-10-21 0:09:43)
00431  * @return ca.mcgill.sable.util.Set
00432  */
00433 private Set getStartingMethods() {
00434     Set startingMds = new ArraySet();
00435     List paraList = new ArrayList();
00436     //"main" method
00437     Hashtable table = CompilationManager.getCompiledClasses();
00438     SootClass mainClass = CompilationManager.getMainSootClass();
00439     if (mainClass.declaresMethod("main"))
00440         startingMds.add(mainClass.getMethod("main"));
00441     else
00442         throw new edu.ksu.cis.bandera.pdgslicer.exceptions.SlicerException("can not find main method");
00443     //"run" methods
00444 
00445     for (java.util.Enumeration e = table.elements(); e.hasMoreElements();) {
00446         SootClass sc = (SootClass) e.nextElement();
00447         if (sc.declaresMethod("run", paraList)) {
00448             startingMds.add(sc.getMethod("run",paraList));
00449         }
00450         //if (sc.getName().equals("java.lang.Object") || (sc.getName().equals("Object")))
00451         if (isObjectClass(sc))
00452             startingMds.addAll(sc.getMethods());
00453     }
00454 
00455     // methods with slice criterion
00456     if (sliceInterestVec.size() == 0)
00457         return startingMds;
00458     for (java.util.Enumeration e = sliceInterestVec.elements(); e.hasMoreElements();) {
00459         SliceInterest sliceInterest = (SliceInterest) e.nextElement();
00460         if (sliceInterest instanceof SliceLocal) {
00461             SliceLocal sliceLocal = (SliceLocal) sliceInterest;
00462             startingMds.add(sliceLocal.getSootMethod());
00463         } else
00464             if (sliceInterest instanceof SlicePoint) {
00465                 SlicePoint slicePoint = (SlicePoint) sliceInterest;
00466                 startingMds.add(slicePoint.getSootMethod());
00467             }
00468             /*
00469             else
00470             if (sliceInterest instanceof SliceField) {
00471             SliceField sliceField = (SliceField) sliceInterest;
00472             SootClass fieldClass = sliceField.getSootClass();
00473             //should see if this field is defined in any method
00474             startingMds.addAll(fieldClass.getMethods());
00475             
00476             }
00477             */
00478     }
00479     return startingMds;
00480 }
00481 /**
00482  * Insert the method's description here.
00483  * Creation date: (00-12-18 10:59:00)
00484  * @return boolean
00485  * @param sootClass ca.mcgill.sable.soot.SootClass
00486  */
00487 private boolean haveStaticFields(SootClass sootClass) {
00488     for (Iterator fdIt = sootClass.getFields().iterator(); fdIt.hasNext();) {
00489         SootField sf = (SootField) fdIt.next();
00490         int modifiers = sf.getModifiers();
00491         if (!Modifier.isPrivate(modifiers) && Modifier.isStatic(modifiers))
00492             return true;
00493     }
00494     return false;
00495 }
00496 /**
00497  * Insert the method's description here.
00498  * Creation date: (00-10-26 20:25:41)
00499  * @return boolean
00500  * @param sm ca.mcgill.sable.soot.SootMethod
00501  */
00502 static boolean isMethodOfObject(SootMethod sm) {
00503     if (isObjectClass(sm.getDeclaringClass()))
00504         return true;
00505     return false;
00506 }
00507 /**
00508  * Insert the method's description here.
00509  * Creation date: (00-10-31 9:27:42)
00510  * @return boolean
00511  * @param sc ca.mcgill.sable.soot.SootClass
00512  */
00513 static boolean isObjectClass(SootClass sc) {
00514     if (sc.getName().equals("java.lang.Object") || sc.getName().equals("Object"))
00515         return true;
00516     return false;
00517 }
00518 /**
00519  * Insert the method's description here.
00520  * Creation date: (00-10-31 16:28:43)
00521  * @return boolean
00522  * @param sootClass ca.mcgill.sable.soot.SootClass
00523  */
00524  static boolean isRemovableClass(SootClass sootClass, Set residualSootClasses) {
00525     if (Slicer.interfaceImplementedByMap.containsKey(sootClass)) {
00526         Set subClasses = (Set) Slicer.interfaceImplementedByMap.get(sootClass);
00527         for (Iterator subIt = subClasses.iterator(); subIt.hasNext();) {
00528             SootClass subClass = (SootClass) subIt.next();
00529             if (residualSootClasses.contains(subClass))
00530                 return false;
00531         }
00532         return true;
00533     }
00534     return true;
00535 }
00536 /**
00537 * Analyse program for building PDG:
00538 * <br>
00539 * {@link MethodCallAnalysis MethodCallAnalysis} --- construcing naive call graph,
00540 * <br>{@link MethodCallAnalysis#MODREFAnalysis() MODREFAnalysis()} --- data flow for fields in classes,
00541 * <br>{@link MethodCallAnalysis#buildMethodPDG(AnnotationManager) buildMethodPDG(cfanns)} --- control and data dependences,
00542 * <br>{@link InterClassAnalysis InterClassAnalysis} --- other dependences.
00543 */
00544 private void moreInformation() {
00545     //this step is to build callMeSiteMap
00546 
00547     System.out.println("   (3) Constructing call graph .... ");
00548     MethodCallAnalysis methodCallAnalysis = new MethodCallAnalysis();
00549     System.out.println("   (4) Data flow for fields in class....");
00550     methodCallAnalysis.MODREFAnalysis();
00551     System.out.println("   (5) Calculating control- and data-dependece for each statement in method ....");
00552     methodCallAnalysis.buildMethodPDG(cfanns);
00553 
00554     //this step is to capture the ready dependence and interference 
00555     //dependence between classes
00556 
00557     if (classInfoList.size() > 1) {
00558         System.out.println("   (6) Inter-class analysis: synchronization, interference ....");
00559         InterClassAnalysis interClassAnalysis = new InterClassAnalysis(classInfoList);
00560     }
00561 }
00562 /**
00563 * Dump slicing result into {@link #residualSootClassArray  residualSootClassArray}.
00564 * <br> Print out summary information on the slicing result.
00565 */
00566 private void outputResidualCls(boolean sliced) {
00567     //residualSootClassArray = new SootClass[classInfoList.size()];
00568     int classnum = 0;
00569     Set unRemovableClasses = new ArraySet();
00570     Set residualSootClassSet = new ArraySet();
00571     List slicedClass = new ArrayList();
00572     for (Iterator classIt = classInfoList.iterator(); classIt.hasNext();) {
00573         ClassInfo classInfo = (ClassInfo) classIt.next();
00574         slicedClass.add(classInfo.sootClass.getName());
00575         residualSootClassSet.add(classInfo.sootClass);
00576         //residualSootClassArray[classnum++] = classInfo.sootClass;
00577     }
00578     if (sliced) {
00579         List removedClass = new ArrayList();
00580         for (int i = 0; i < relevantClassArray.length; i++) {
00581             SootClass relClass = relevantClassArray[i];
00582             if (slicedClass.contains(relClass.getName())) {
00583                 if (Slicer.unreachableClasses.contains(relClass))
00584                     Slicer.unreachableClasses.remove(relClass);
00585                 continue;
00586             }
00587             if (Slicer.unreachableClasses.contains(relClass)) {
00588             } else
00589                 if (isRemovableClass(relClass, residualSootClassSet))
00590                     removedClass.add(relClass.getName());
00591                 else {
00592                     residualSootClassSet.add(relClass);
00593                     unRemovableClasses.add(relClass);
00594                 }
00595         }
00596         residualSootClassArray = new SootClass[classInfoList.size() + unRemovableClasses.size()];
00597         for (Iterator classIt = classInfoList.iterator(); classIt.hasNext();) {
00598             ClassInfo classInfo = (ClassInfo) classIt.next();
00599             residualSootClassArray[classnum++] = classInfo.sootClass;
00600         }
00601         for (Iterator classIt = unRemovableClasses.iterator(); classIt.hasNext();) {
00602             residualSootClassArray[classnum++] = (SootClass) classIt.next();
00603         }
00604         if (classnum == 0)
00605             residualSootClassArray = null;
00606         System.out.print("\nSuccessfully slicing " + classnum + " vs. " + classNum);
00607         System.out.println(" classes: " + residualSootClassSet);
00608         if (!removedClass.isEmpty()) {
00609             if (removedClass.size() > 1)
00610                 System.out.println(removedClass.size() + " classes are removed by slicer: " + removedClass);
00611             else
00612                 System.out.println(removedClass.size() + " class is removed by slicer: " + removedClass);
00613         }
00614         if (!Slicer.unreachableClasses.isEmpty()) {
00615             if (Slicer.unreachableClasses.size() > 1) {
00616                 System.out.println(Slicer.unreachableClasses.size() + " classes are unreachable: " + Slicer.unreachableClasses);
00617             } else
00618                 System.out.println(Slicer.unreachableClasses.size() + " class is unreachable: " + Slicer.unreachableClasses);
00619         }
00620         //System.out.println("\n" + slicedClass.size() + " classes are remained: " + slicedClass + "\n");
00621     } else {
00622         residualSootClassArray = new SootClass[classInfoList.size()];
00623         for (Iterator classIt = classInfoList.iterator(); classIt.hasNext();) {
00624             ClassInfo classInfo = (ClassInfo) classIt.next();
00625             residualSootClassArray[classnum++] = classInfo.sootClass;
00626         }
00627         System.out.println("\nKeeping all " + classNum + " classes without slicing: " + slicedClass);
00628         //System.out.println("\n" + slicedClass.size() + " classes are remained: " + slicedClass + "\n");
00629     }
00630 }
00631 /**
00632  * Insert the method's description here.
00633  * Creation date: (00-12-5 10:09:36)
00634  */
00635 private void postProcessing() {
00636     System.out.println("\nConstructing residual program ......");
00637     PostProcess postProcess = new PostProcess(classInfoList, cfanns);
00638 
00639     //modify sootclass according to the slice set
00640     postProcess.resClassCons();
00641 
00642     //Output of the residual classes
00643 
00644     outputResidualCls(true);
00645 }
00646 /**
00647  * Insert the method's description here.
00648  * Creation date: (00-12-5 10:09:36)
00649  */
00650 public void postProcessingOnAnnotation() {
00651     System.out.println("Postprocessing ... ...");
00652     postProcessOnAnnotation = new PostProcessOnAnnotation(classInfoList, cfanns);
00653     postProcessOnAnnotation.resClassCons();
00654     System.out.println("End of post-processing");
00655 }
00656 /**
00657  * Insert the method's description here.
00658  * Creation date: (00-12-5 10:11:32)
00659  */
00660 public boolean preProcessing(Vector sliceCriterionVector) {
00661     boolean emptyCriterion = false;
00662     //extract slicing criterion
00663     System.out.println("\n   (2) Extracting slicing criterion ......");
00664     PreProcess preProcess = new PreProcess(classInfoList);
00665     if (sliceCriterionVector.size() == 0)
00666         preProcess.extractingForDL(relevantClassArray);
00667     else
00668         preProcess.extracting(sliceCriterionVector);
00669     if (preProcess.emptySliceCriterion()) {
00670         System.out.println("       *** There is no slicing criterion provided;");
00671         System.out.println("       *** And there is no slicing criterion for deadlock checking can be extracted.");
00672         outputResidualCls(false);
00673         emptyCriterion = true;
00674         return emptyCriterion;
00675     }
00676     System.out.println("\nSlicing criterion from extracting and grouping: \n");
00677     printCriterion();
00678     System.out.println("\n");
00679     emptyCriterion = false;
00680     return emptyCriterion;
00681 }
00682 /**
00683 * Print out slicing criterion for each class and method.
00684 */
00685 public void printCriterion() {
00686     for (Iterator classIt = classInfoList.iterator(); classIt.hasNext();) {
00687         ClassInfo classInfo = (ClassInfo) classIt.next();
00688         String className = classInfo.sootClass.getName();
00689         List methodList = classInfo.methodsInfoList;
00690         for (Iterator mdIt = methodList.iterator(); mdIt.hasNext();) {
00691             MethodInfo mdInfo = (MethodInfo) mdIt.next();
00692             String methodName = mdInfo.sootMethod.getName();
00693             if (mdInfo.sCriterion == null)
00694                 continue;
00695             System.out.print("Criterion of " + className + "." + methodName + " is: ");
00696             System.out.println(mdInfo.sCriterion);
00697             System.out.println();
00698         }
00699     }
00700 }
00701 /**
00702 * Print out Jimple code of a soot class.
00703 * <br> This method is only for internal debugging.
00704 * <p>
00705 * @param sClass a soot class being printed.
00706 */
00707 static void printJimpleClass(SootClass sClass) {
00708     // Print Jimple class
00709     PrintWriter out = new PrintWriter(System.out, true);
00710     sClass.printTo(new StoredBody(Jimple.v()), out);
00711 }
00712 /**
00713 * Get result of slicing as an array of {@link SootClass SootClass}.
00714 */
00715 public SootClass[] result() {
00716     return residualSootClassArray;
00717 }
00718 /**
00719 * Start the slicer after creating an object of {@link Slicer Slicer}.
00720 * <br>
00721 * Four steps are included in this method:
00722 * <ul>
00723    * <li> {@link #basicInformation() basicInformation} --- Collect some basic information of program;
00724    * <li> {@link PreProcess PreProcess} --- Determine slicing criterion;
00725    * <li> {@link #moreInformation() moreInformation()} --- Build program dependency graph for each method in the program;
00726    * <li> {@link #slicing() slicing()} --- Slice each method in the program,
00727    * construct residual program, and dump residual program.
00728    * </ul>
00729 */
00730 public void run() throws Exception {
00731             //System.out.println("method variant manager key set 2: " + edu.ksu.cis.bandera.bofa.MethodVariantManager.methodMap);
00732     try {
00733         if (Slicer.Turn_On_BOFA) {
00734             edu.ksu.cis.bandera.bofa.BOFA.reset();
00735             edu.ksu.cis.bandera.bofa.BOFA.analyze();
00736             BOFA_Analysis = edu.ksu.cis.bandera.bofa.Analysis.init();
00737         }
00738         //dumpJimpleCode(relevantClassArray, ".originalBUI2.jimple");
00739         System.out.println("\nCollecting reachable methods ......");
00740         //System.out.println("method variant manager key set: " + edu.ksu.cis.bandera.bofa.MethodVariantManager.methodMap.keySet());
00741         buildInterfaceAndSuperClassMap();
00742         collectReachableMethods();
00743         System.out.println("\nBuilding Program Dependence Graph ......");
00744         System.out.println("\n   (1) Collecting information for each method ......");
00745         basicInformation(); //with classes
00746         //extract slicing criterion
00747         boolean emptyCriterion = preProcessing(sliceInterestVec);
00748         if (emptyCriterion)
00749             return;
00750         collectOriginalMethods();
00751         moreInformation(); //with cfanns
00752         slicing(); //wiht cfanns
00753         //dumpJimpleCode(residualSootClassArray, ".slicedBUI2.jimple");
00754         postProcessing();
00755     } catch (Exception eee) {
00756         System.out.println("There is exception in slicer");
00757         eee.printStackTrace();
00758         throw eee;
00759     }
00760 }
00761 /**
00762 * Slice each method need to be sliced ---
00763 * {@link #slicingMethods() slicingMethods()};
00764 * <br>Postprocess for slicing --- {@link PostProcess PostProcess}.
00765 * <br>Dump slicing result --- {@link #outputResidualCls(boolean) outputResidualCls}.
00766 */
00767 public void slicing() {
00768     //for concurrent program, slicing criterion may relate to several class
00769     //preProcess.extracting() will extract slicing criterion from one or more
00770     //specification items, and distribute the slicing criterion into each 
00771     //relative class and method. Then store these slicing criterion flap to 
00772     //corresponding class and method information class
00773     System.out.println("\nSlicing .........\n");
00774     slicingMethods(); //with Slicer.sootMethodInfoMap
00775     //slice set for every method of every class is in MethodInfo class
00776     //slicing.getSliceSets() will return a new class list where the
00777     //slice sets are not null
00778 }
00779 /**
00780  * Slice each method with {@link SlicingMethod SlicingMethod}.
00781  * <p>
00782  * The process of slicing is fix point reaching process:
00783  * <br> (UP U DOWN)*( slicing criterion)
00784  * <br> where UP and DOWN is constraint call graph driven up and down.
00785  */
00786 private void slicingMethods() {
00787     for (Iterator mdIt = sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00788         SootMethod sootMethod = (SootMethod) mdIt.next();
00789         if (isMethodOfObject(sootMethod)) continue;
00790         MethodInfo mdInfo = (MethodInfo) sootMethodInfoMap.get(sootMethod);
00791         SlicingMethod smd = new SlicingMethod(mdInfo);
00792         smd.slicingMethod(true);
00793     }
00794 
00795     //Slicing again by the incremental slicing criterion
00796 
00797     while (SlicingMethod.criterionChanged) {
00798         SlicingMethod.criterionChanged = false; 
00799         for (Iterator mdIt = sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00800             SootMethod sootMethod = (SootMethod) mdIt.next();
00801             if (isMethodOfObject(sootMethod)) continue;
00802             MethodInfo mdInfo = (MethodInfo) sootMethodInfoMap.get(sootMethod);
00803             if (mdInfo.increCriterion != null) {
00804                 SlicingMethod smd = new SlicingMethod(mdInfo);
00805                 smd.slicingMethodAgain();
00806             }
00807         }
00808     }
00809 }
00810 }

Generated at Thu Feb 7 06:55:01 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001