1 50 package net.sf.just4log.transform; 51 52 import java.util.Iterator ; 53 import java.util.LinkedList ; 54 55 import net.sf.just4log.NoMatchingInvokeInterfaceInstruction; 56 57 import org.apache.bcel.classfile.Field; 58 import org.apache.bcel.classfile.JavaClass; 59 import org.apache.bcel.classfile.Method; 60 import org.apache.bcel.generic.ClassGen; 61 import org.apache.bcel.generic.ConstantPoolGen; 62 import org.apache.bcel.generic.GETSTATIC; 63 import org.apache.bcel.generic.Instruction; 64 import org.apache.bcel.generic.InstructionFactory; 65 import org.apache.bcel.generic.InstructionHandle; 66 import org.apache.bcel.generic.InstructionList; 67 import org.apache.bcel.generic.InvokeInstruction; 68 import org.apache.bcel.generic.MethodGen; 69 import org.apache.bcel.generic.ObjectType; 70 import org.apache.bcel.generic.ReturnInstruction; 71 import org.apache.bcel.generic.Type; 72 import org.apache.commons.logging.Log; 73 import org.apache.commons.logging.LogFactory; 74 75 78 79 public abstract class Transform { 80 private static Log logger = LogFactory.getLog(Transform.class); 81 private static String CLASSID = 82 "$Id: Transform.java,v 1.15 2003/09/23 21:21:15 lbruand Exp $"; 83 84 static { 85 ApacheCommonTransform.register(); 86 Log4jTransform.register(); 87 LogJDK14Transform.register(); 88 } 89 90 InstructionFactory instFact; 91 private String classname; 92 93 96 public Transform() { 97 super(); 98 } 99 100 private static LinkedList transmap; 101 public static void register(Transform trans) { 102 if (transmap == null) { 103 transmap = new LinkedList (); 104 } 105 106 synchronized (transmap) { 107 transmap.add(trans); 108 } 109 110 } 111 112 public static Transform getTransformationForJavaClass( 113 JavaClass claz, 114 ConstantPoolGen cp) { 115 Field[] fields = claz.getFields(); 116 ObjectType fieldType; 117 Transform t; 118 for (int i = 0; i < fields.length; i++) { 119 120 try { 121 fieldType = (ObjectType) fields[i].getType(); 122 } catch (ClassCastException ex) { 123 continue; 124 } 125 for (Iterator j = transmap.iterator(); j.hasNext();) { 126 t = (Transform) j.next(); 127 if (fieldType.equals(t.getLogType()) 128 || fieldType.isCastableTo(t.getLogType())) { 129 logger.info( 130 "Found logger attribute: " 131 + fieldType 132 + " " 133 + fields[i].getName()); 134 t.init(claz, fields[i], cp); 135 return t; 136 } 137 } 138 139 } 140 return null; 141 } 142 JavaClass clazz; 143 Field loggerAttribute; 144 public void init(JavaClass clazz, Field logger, ConstantPoolGen cp) { 145 this.clazz = clazz; 146 this.loggerAttribute = logger; 147 this.instFact = new InstructionFactory(cp); 148 } 149 public void done() { 150 this.loggerAttribute = null; 151 this.instFact = null; 152 } 153 public abstract InstructionHandle insertFork( 154 InstructionList il, 155 InstructionHandle getStaticHandle, 156 InstructionHandle invokeHandle, 157 ConstantPoolGen cp); 158 159 public abstract InstructionHandle insertEnter( 160 MethodGen orig, 161 InstructionList il, 162 InstructionHandle firstInstructionHandle, 163 ConstantPoolGen cp); 164 165 public abstract InstructionHandle insertExit( 166 MethodGen orig, 167 InstructionList il, 168 InstructionHandle returnInstructionHandle, 169 ConstantPoolGen cp); 170 171 public void transform( 172 MethodGen mg, 173 InstructionList il, 174 InstructionHandle handle, 175 ConstantPoolGen cp) 176 throws NoMatchingInvokeInterfaceInstruction { 177 178 logger.info("Found a logger instruction."); 179 InstructionHandle lastLogHandle = handle; 180 181 InvokeInstruction invokeInterface = null; 182 Instruction inst = null; 183 while (true) { 184 handle = handle.getNext(); 185 if (handle == null) { 186 logger.warn("No matching invokeInterface found."); 187 throw new NoMatchingInvokeInterfaceInstruction("No matching invokeInterface found."); 188 } 189 inst = handle.getInstruction(); 190 if (inst instanceof InvokeInstruction) { 191 invokeInterface = (InvokeInstruction) inst; 192 if (invokeInterface.getClassType(cp).equals(getLogType())) { 193 logger.info("Found matching invokeInstruction."); 194 if (level_logs == FORKLOGS) { 195 InstructionHandle insertHandle = 196 insertFork(il, lastLogHandle, handle, cp); 197 if (insertHandle != null) { 198 il.redirectBranches(lastLogHandle, insertHandle); 199 il.redirectExceptionHandlers( 200 mg.getExceptionHandlers(), 201 lastLogHandle, 202 insertHandle); 203 il.redirectLocalVariables( 204 mg.getLocalVariables(), 205 lastLogHandle, 206 insertHandle); 207 } 208 } 209 210 break; 211 } 212 } 213 } 214 } 215 216 224 public Method speedup(Method orig, MethodGen mg, ConstantPoolGen cp) 225 throws NoMatchingInvokeInterfaceInstruction { 226 logger.info("Entry speedup(Method " + mg.getName() + ")"); 227 if (orig.getName().equals("<clinit>") 228 || orig.getName().equals("<init>") 229 || orig.getName().equals("class$")) { 230 logger.info( 231 "This method " 232 + mg.getName() 233 + " is a special method and won't be modified."); 234 return orig; 235 } 236 InstructionList il = null; 237 InstructionHandle handle = null; 238 Instruction inst = null; 239 240 GETSTATIC getStatic = null; 241 242 Method m = null; 243 244 try { 245 il = mg.getInstructionList(); 246 handle = il.getStart(); 247 if (level_enters == SIMPLEENTER) { 248 249 insertEnter(mg, il, handle, cp); 250 insertFork(il, il.getStart(), handle.getPrev(), cp); 251 } 252 253 for (; handle != null; handle = handle.getNext()) { 254 inst = handle.getInstruction(); 255 logger.info("next instruction: " + inst); 256 if (level_exits == SIMPLEEXIT 257 && inst instanceof ReturnInstruction) { 258 InstructionHandle lastLogHandle = handle; 259 logger.info( 260 "Found a ReturnInstruction of type: " 261 + inst.toString()); 262 int stackSize = 263 inst.consumeStack(cp) - inst.produceStack(cp); 264 while (stackSize != 0) { 265 handle = handle.getPrev(); 266 inst = handle.getInstruction(); 267 logger.info("prev instruction: " + inst); 268 stackSize += inst.consumeStack(cp) 269 - inst.produceStack(cp); 270 } 271 272 InstructionHandle insertHandle = 273 insertExit(mg, il, handle, cp); 274 if (insertHandle != null) { 275 il.redirectBranches(handle, insertHandle); 278 il.redirectExceptionHandlers( 279 mg.getExceptionHandlers(), 280 handle, 281 insertHandle); 282 il.redirectLocalVariables( 283 mg.getLocalVariables(), 284 handle, 285 insertHandle); 286 handle = 287 insertFork(il, insertHandle, handle.getPrev(), cp); 288 il.redirectBranches(insertHandle, handle ); 289 il.redirectExceptionHandlers( 290 mg.getExceptionHandlers(), 291 insertHandle, 292 handle); 293 il.redirectLocalVariables( 294 mg.getLocalVariables(), 295 insertHandle, 296 handle); 297 } 298 299 handle = lastLogHandle; 300 } 301 if (inst instanceof GETSTATIC) { 302 getStatic = (GETSTATIC) inst; 303 Type type = getStatic.getFieldType(cp); 304 logger.info( 305 "Found a GETSTATIC instruction of type: " 306 + type.toString()); 307 308 if (getStatic 309 .getFieldName(cp) 310 .equals(loggerAttribute.getName())) { 311 logger.info("This is a logger access"); 312 transform(mg, il, handle, cp); 313 } 314 } 315 } 316 if (orig.getLineNumberTable() == null) { 317 logger.info("Removing line numbers"); 318 mg.removeLineNumbers(); 319 } 320 if (orig.getLocalVariableTable() == null) { 321 logger.info("Removing Local variables table"); 322 mg.removeLocalVariables(); 323 } 324 m = mg.getMethod(); 325 } finally { 326 327 il.dispose(); 328 } 329 return m; 330 } 331 337 public static JavaClass speedup(JavaClass source) { 338 try { 339 logger.info("Entry speedup(JavaClass)"); 340 ClassGen cg = new ClassGen(source); 341 Method[] methods = cg.getMethods(); 342 ConstantPoolGen cp = cg.getConstantPool(); 343 344 Transform trans = getTransformationForJavaClass(source, cp); 345 if (trans == null) { 346 logger.warn( 347 "No transformer found for class " + source.getClassName()); 348 return source; 349 } 350 for (int i = 0; i < methods.length; i++) { 351 if (!(methods[i].isAbstract() || methods[i].isNative())) { 352 MethodGen mg = 353 new MethodGen(methods[i], source.getClassName(), cp); 354 Method stripped = trans.speedup(methods[i], mg, cp); 355 if (stripped != null) 356 cg.replaceMethod(methods[i], stripped); 357 } 358 } 359 trans.done(); 360 JavaClass target = cg.getJavaClass(); 361 target.setFileName(source.getFileName()); 362 return target; 363 } catch (Exception e) { 364 e.printStackTrace(); 365 } 366 return source; 367 368 } 369 public static String getMethodRepr(MethodGen mg) { 370 StringBuffer sb = 371 new StringBuffer (mg.getReturnType() + " " + mg.getName() + "("); 372 Type[] types = mg.getArgumentTypes(); 373 for (int i = 0; i < types.length; i++) { 374 if (i != 0) { 375 sb.append(", "); 376 } 377 sb.append(types[i].toString()); 378 } 379 sb.append(")"); 380 logger.info("Method representation to enter: " + sb.toString()); 381 return sb.toString(); 382 } 383 386 public abstract ObjectType getLogType(); 387 388 public static final int NOEXIT = 0; 389 public static final int SIMPLEEXIT = 1; 390 public static final int PARAMETEREXIT = 2; 391 392 public static int level_exits = NOEXIT; 393 394 public static final int REMOVELOGS = 0; 395 public static final int LEAVELOGS = 1; 396 public static final int FORKLOGS = 2; 397 public static int level_logs = FORKLOGS; 398 399 public static final int NOENTER = 0; 400 public static final int SIMPLEENTER = 1; 401 public static final int PARAMETERENTER = 2; 402 public static int level_enters = NOENTER; 403 public static final String ENTER_STRING = "enters: "; 404 public static final String EXIT_STRING = "exits: "; 405 } 406 | Popular Tags |