1 package alt.jiapi.interceptor; 2 3 import java.util.List ; 4 5 import java.lang.reflect.InvocationHandler ; 6 import java.lang.reflect.Method ; 7 import java.lang.reflect.Modifier ; 8 9 import alt.jiapi.InstrumentationException; 10 11 import alt.jiapi.event.EventInstrumentor; 12 import alt.jiapi.event.EventRuntime; 13 14 import alt.jiapi.reflect.Instruction; 15 import alt.jiapi.reflect.InstructionFactory; 16 import alt.jiapi.reflect.InstructionList; 17 import alt.jiapi.reflect.JiapiClass; 18 import alt.jiapi.reflect.JiapiField; 19 import alt.jiapi.reflect.JiapiMethod; 20 import alt.jiapi.reflect.Loader; 21 import alt.jiapi.reflect.Signature; 22 import alt.jiapi.reflect.SignatureUtil; 23 24 import alt.jiapi.reflect.FieldExistsException; 25 import alt.jiapi.reflect.MethodExistsException; 26 27 import alt.jiapi.reflect.instruction.Invocation; 28 import alt.jiapi.reflect.instruction.OpcodeGroups; 29 import alt.jiapi.reflect.instruction.Opcodes; 30 31 import alt.jiapi.instrumentor.HotSpot; 32 33 import org.apache.log4j.Category; 34 35 40 class InvocationInstrumentor extends EventInstrumentor { 41 private static Category log = Category.getInstance(InvocationInstrumentor.class); 42 43 private InvocationHandler handler; 44 45 InvocationInstrumentor(InvocationInterceptor ii, InvocationHandler handler) { 46 super(ii); 47 this.handler = handler; 48 } 49 50 public void instrument(JiapiMethod jm) { 51 InstructionList il = jm.getInstructionList(); 52 53 if ("<clinit>".equals(jm.getName())) { 54 return; 55 } 56 57 InstructionFactory factory = il.getInstructionFactory(); 58 JiapiClass ii = getEventProducer(); 59 JiapiMethod invokeMethod = null; 60 61 try { 62 invokeMethod = 63 ii.getDeclaredMethod("invokeMethod", 64 new String [] { "java.lang.Object", 65 "java.lang.String", 66 "java.lang.Object[]", 67 "java.lang.String"}); 68 } 69 catch(Exception e) { 70 e.printStackTrace(); 71 } 72 73 74 int idx = -1; 75 while ((idx = il.indexOf(OpcodeGroups.INVOKE_INSTRUCTIONS, idx+1)) != -1) { 76 Invocation ins = (Invocation)il.get(idx); 77 if (!match(ins.getClassName() + "." + ins.getMethodName())) { 78 continue; 79 } 80 81 82 101 if (ins.getOpcode() != Opcodes.INVOKESTATIC && 103 ins.getOpcode() != Opcodes.INVOKEVIRTUAL) { 104 continue; 105 } 106 107 JiapiField interceptor = getEventProducerField(); 108 109 InstructionList nList = new InstructionList(); 111 112 113 ArgumentList al = createArgumentLists(il, idx); 117 InstructionList[] pLists = al.arguments; 118 int paramIdx = al.paramIndex; 119 120 short opCode = ins.getOpcode(); 121 if (opCode == Opcodes.INVOKEVIRTUAL || 122 opCode == Opcodes.INVOKESPECIAL) { 123 paramIdx--; } 125 126 switch(opCode) { 129 case Opcodes.INVOKEVIRTUAL: 130 case Opcodes.INVOKESTATIC: 131 132 nList.add(factory.getField(interceptor)); if (opCode == Opcodes.INVOKESTATIC) { 134 addClassForNameInstructions(ins.getClassName(), nList); 136 137 } 138 else { 139 nList.add(il.get(paramIdx)); } 141 142 String mName = ins.getMethodName(); 143 nList.add(factory.pushConstant(mName)); 145 nList.add(factory.newArray("java.lang.Object", 146 ins.getParameterTypes().length)); 147 148 String [] i_params = ins.getParameterTypes(); 149 for (int i = 0; i < pLists.length; i++) { 151 if ("long".equals(i_params[i])) { 152 nList.add(factory.dup()); 153 } 154 else if ("double".equals(i_params[i])) { 155 nList.add(factory.dup()); 156 } 157 else { 158 nList.add(factory.dup()); 159 } 160 nList.add(factory.pushConstant(i)); 161 nList.add(pLists[i]); 162 nList.add(factory.aastore()); 163 } 164 165 nList.add(factory.pushConstant(ins.getClassName() + ins.getMethodName() + ins.getDescriptor())); 169 170 nList.add(factory.invoke(invokeMethod)); 172 173 handleReturnValue(nList, ins); 174 175 176 il.replace(paramIdx, idx + 1, nList); 179 180 break; 181 } 182 183 idx = paramIdx + nList.size() - 1; 186 } 187 } 188 189 190 191 192 196 private ArgumentList createArgumentLists(InstructionList il, int invocationIndex) { 197 Invocation ins = (Invocation)il.get(invocationIndex); 198 199 201 String [] paramTypes = ins.getParameterTypes(); 202 InstructionList[] argList = 203 new InstructionList[paramTypes.length]; 204 205 int pIdx = invocationIndex - 1; 207 208 for (int i = argList.length - 1; i >= 0; i--) { 210 int stackUsage = ins.stackConsumption(); 211 InstructionList pList = il.createEmptyList(); 212 213 boolean primitive = SignatureUtil.isPrimitive(paramTypes[i]); 214 Instruction pr_ins = null; 215 216 if (primitive) { 217 pr_ins = handlePrimitiveType(paramTypes[i], pList); 218 } 219 220 int insertIdx = pList.size(); 221 while ((stackUsage > 0 && ins.getOpcode() == Opcodes.INVOKESTATIC)|| 224 (stackUsage > 1 && ins.getOpcode() == Opcodes.INVOKEVIRTUAL)) { 225 Instruction pIns = il.get(pIdx); 226 stackUsage -= pIns.stackUsage(); 229 230 pList.insert(insertIdx, pIns); 234 pIdx--; 235 } 236 237 if (primitive) { 238 pList.add(pr_ins); } 240 241 argList[i] = pList; 242 } 243 244 return new ArgumentList(argList, pIdx+1); 247 } 248 249 250 253 private Instruction handlePrimitiveType(String type, InstructionList il) { 254 InstructionFactory f = il.getInstructionFactory(); 255 String cName = null; 256 Signature s = new Signature("void", new String []{ type }); 257 258 if ("int".equals(type)) { 259 cName = "java.lang.Integer"; 260 } 261 else if ("long".equals(type)) { 262 cName = "java.lang.Long"; 263 } 264 else if ("char".equals(type)) { 265 cName = "java.lang.Character"; 266 } 267 else if ("boolean".equals(type)) { 268 cName = "java.lang.Boolean"; 269 } 270 else if ("byte".equals(type)) { 271 cName = "java.lang.Byte"; 272 } 273 else if ("float".equals(type)) { 274 cName = "java.lang.Float"; 275 } 276 else if ("double".equals(type)) { 277 cName = "java.lang.Double"; 278 } 279 280 il.add(f.newClass(cName)); 281 il.add(f.dup()); 282 Instruction ins = f.invoke(Modifier.PUBLIC, cName, "<init>", s); 283 return ins; 284 } 285 286 287 private void handleReturnValue(InstructionList il, Invocation ins) { 288 InstructionFactory factory = il.getInstructionFactory(); 290 String rType = ins.getReturnType(); 291 292 if ("int".equals(rType)) { 293 try { 294 JiapiClass jc = new Loader().loadClass("java.lang.Integer"); 295 JiapiMethod jm = 296 jc.getDeclaredMethod("intValue", new String [0]); 297 298 il.add(factory.cast("java.lang.Integer")); 299 il.add(factory.invoke(jm)); 300 } 301 catch(Exception e) { 302 e.printStackTrace(); 303 } 304 } 305 else if ("long".equals(rType)) { 306 try { 307 JiapiClass jc = new Loader().loadClass("java.lang.Long"); 308 JiapiMethod jm = 309 jc.getDeclaredMethod("longValue", new String [0]); 310 311 il.add(factory.cast("java.lang.Long")); 312 il.add(factory.invoke(jm)); 313 } 314 catch(Exception e) { 315 e.printStackTrace(); 316 } 317 } 318 else if ("char".equals(rType)) { 319 try { 320 JiapiClass jc = new Loader().loadClass("java.lang.Character"); 321 JiapiMethod jm = 322 jc.getDeclaredMethod("charValue", new String [0]); 323 324 il.add(factory.cast("java.lang.Character")); 325 il.add(factory.invoke(jm)); 326 } 327 catch(Exception e) { 328 e.printStackTrace(); 329 } 330 } 331 else if ("boolean".equals(rType)) { 332 try { 333 JiapiClass jc = new Loader().loadClass("java.lang.Boolean"); 334 JiapiMethod jm = 335 jc.getDeclaredMethod("booleanValue", new String [0]); 336 337 il.add(factory.cast("java.lang.Boolean")); 338 il.add(factory.invoke(jm)); 339 } 340 catch(Exception e) { 341 e.printStackTrace(); 342 } 343 } 344 else if ("byte".equals(rType)) { 345 try { 346 JiapiClass jc = new Loader().loadClass("java.lang.Byte"); 347 JiapiMethod jm = 348 jc.getDeclaredMethod("byteValue", new String [0]); 349 350 il.add(factory.cast("java.lang.Byte")); 351 il.add(factory.invoke(jm)); 352 } 353 catch(Exception e) { 354 e.printStackTrace(); 355 } 356 } 357 else if ("float".equals(rType)) { 358 try { 359 JiapiClass jc = new Loader().loadClass("java.lang.Float"); 360 JiapiMethod jm = 361 jc.getDeclaredMethod("floatValue", new String [0]); 362 363 il.add(factory.cast("java.lang.Float")); 364 il.add(factory.invoke(jm)); 365 } 366 catch(Exception e) { 367 e.printStackTrace(); 368 } 369 } 370 else if ("double".equals(rType)) { 371 try { 372 JiapiClass jc = new Loader().loadClass("java.lang.Double"); 373 JiapiMethod jm = 374 jc.getDeclaredMethod("doubleValue", new String [0]); 375 376 il.add(factory.cast("java.lang.Double")); 377 il.add(factory.invoke(jm)); 378 } 379 catch(Exception e) { 380 e.printStackTrace(); 381 } 382 } 383 else if ("void".equals(rType)){ 384 il.add(new Instruction(new byte[]{Opcodes.POP})); 387 } 388 else { il.add(factory.cast(ins.getReturnType())); 390 } 391 } 392 393 394 private void addClassForNameInstructions(String name, InstructionList il) { 395 InstructionFactory f = il.getInstructionFactory(); 396 397 InstructionList nl = il.createEmptyList(); 398 399 try { 404 nl.add(f.pushConstant(name)); 405 nl.add(f.invoke(Modifier.STATIC, "java.lang.Class", 406 "forName", new Signature("java.lang.Class", 407 new String [] {"java.lang.String"}))); 408 } 409 catch(Exception e) { 410 e.printStackTrace(); 411 il.add(f.pushNull()); 412 } 413 414 il.add(nl); 415 } 416 417 418 private class ArgumentList { 419 public InstructionList[] arguments; 420 public int paramIndex; 421 422 public ArgumentList(InstructionList[] args, int paramIndex) { 423 this.arguments = args; 424 this.paramIndex = paramIndex; 425 } 426 } 427 } 428 | Popular Tags |