001 package edu.rice.cs.cunit.instrumentors.util;
002
003 import edu.rice.cs.cunit.classFile.ClassFile;
004 import edu.rice.cs.cunit.classFile.MethodInfo;
005 import edu.rice.cs.cunit.classFile.attributes.CodeAttributeInfo;
006 import edu.rice.cs.cunit.classFile.code.InstructionList;
007 import edu.rice.cs.cunit.classFile.code.Opcode;
008 import edu.rice.cs.cunit.classFile.code.instructions.GenericInstruction;
009 import edu.rice.cs.cunit.classFile.constantPool.ClassPoolInfo;
010 import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckClassVisitor;
011 import edu.rice.cs.cunit.util.Types;
012
013 import java.util.ArrayList;
014 import java.util.List;
015
016 /**
017 * Instrumentation strategy that scans for a "new Object()" operation.
018 *
019 * @author Mathias Ricken
020 */
021 public class ScanForObjectCtorStrategy implements IScannerStrategy {
022 /**
023 * The separator string between class name and method signature.
024 */
025 public static final String CLASS_SIG_SEPARATOR_STRING = "::";
026
027 /**
028 * Storage class for locations that used "new Object()".
029 */
030 public static class Location implements IScannerStrategy.IScanResult {
031 /**
032 * Name of the class that contains the operation.
033 */
034 public final String className;
035
036 /**
037 * Name of the method.
038 */
039 public final String methodName;
040
041 /**
042 * Descriptor of the method.
043 */
044 public final String methodDescriptor;
045
046 /**
047 * Program counter value where it was used.
048 */
049 public final int pc;
050
051 /**
052 * Constructor for a usage location.
053 * @param className class name
054 * @param methodName method name
055 * @param methodDescriptor method descriptor
056 * @param pc program counter
057 */
058 public Location(String className, String methodName, String methodDescriptor, int pc) {
059 this.className = className;
060 this.methodName = methodName;
061 this.methodDescriptor = methodDescriptor;
062 this.pc = pc;
063 }
064
065 /**
066 * Returns a string representation of the object.
067 * @return a string representation of the object.
068 */
069 public String toString() {
070 return className+CLASS_SIG_SEPARATOR_STRING+methodName+methodDescriptor+", PC="+String.valueOf(pc);
071 }
072
073 /**
074 * Return the name of the property that was scanned for.
075 * @return property name
076 */
077 public String getPropertyName() {
078 return "Uses of new Object()";
079 }
080 }
081
082 /**
083 * List of usage locations.
084 */
085 ArrayList<Location> _locations = new ArrayList<Location>();
086
087 /**
088 * Returns the list of usage locations.
089 * @return list of usage locations
090 */
091 public List<Location> getScanResults() {
092 return _locations;
093 }
094
095 /**
096 * Instrument the class.
097 *
098 * @param cf class file info
099 */
100 public void instrument(final ClassFile cf) {
101 for(MethodInfo mi: cf.getMethods()) {
102 if (((mi.getAccessFlags() & (ClassFile.ACC_NATIVE | ClassFile.ACC_ABSTRACT)) == 0)) {
103 CodeAttributeInfo codeAttr = mi.getCodeAttributeInfo();
104 InstructionList il = new InstructionList(codeAttr.getCode());
105 do {
106 if ((il.getOpcode()==Opcode.NEW) ||
107 (il.getOpcode()==Opcode.NEW_QUICK))
108 {
109 GenericInstruction gi = (GenericInstruction)il.getInstr();
110 short index = Types.shortFromBytes(gi.getBytecode(), 1);
111 ClassPoolInfo cpi = cf.getConstantPool().get(index).execute(CheckClassVisitor.singleton(), null);
112 if (cpi.getName().toString().equals("java/lang/Object")) {
113 _locations.add(new Location(cf.getThisClassName(),
114 mi.getName().toString(),
115 mi.getDescriptor().toString(),
116 il.getPCFromIndex(il.getIndex())));
117 }
118 }
119 } while(il.advanceIndex());
120 }
121 }
122 }
123
124 /**
125 * Instrumentation of all classes is done.
126 */
127 public void done() {
128 // nothing to do
129 }
130 }