1 18 19 package alt.jiapi.reflect; 20 21 import java.lang.reflect.Modifier ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.LinkedList ; 25 26 import org.apache.log4j.Category; 27 28 import alt.jiapi.Runtime; 29 30 import alt.jiapi.file.Attribute; 31 import alt.jiapi.file.ClassFile; 32 import alt.jiapi.file.CodeAttribute; 33 import alt.jiapi.file.ConstantPool; 34 import alt.jiapi.file.ExceptionsAttribute; 35 import alt.jiapi.file.LineNumberTableAttribute; 36 import alt.jiapi.file.LocalVariableTableAttribute; 37 import alt.jiapi.file.Method; 38 import alt.jiapi.file.SyntheticAttribute; 39 40 import alt.jiapi.reflect.instruction.Opcodes; 41 42 51 52 59 public class JiapiMethod { 60 private static Category log = Runtime.getLogCategory(JiapiMethod.class); 61 62 private Method method; 63 private Signature signature; 64 private JiapiClass declaringClass; 65 66 private InstructionList instructions; 67 private TryBlock[] tryBlocks = null; 68 69 private List lineNumberTable; 70 private List exceptionTable; 71 72 73 76 public JiapiMethod(Method m) { 77 this.method = m; 78 this.signature = new Signature(m.getDescriptor()); 79 } 80 81 82 83 88 public String getName() { 89 return method.getName(); 90 } 91 92 98 public int getModifiers() { 99 return method.getAccessFlags(); 100 } 101 102 104 109 public String getReturnType() { 110 return signature.getReturnType(); 111 } 112 113 118 public Signature getSignature() { 119 return signature; 120 } 121 122 123 126 public InstructionFactory getInstructionFactory() { 127 return new InstructionFactory(method.getConstantPool()); 128 } 129 130 131 136 public InstructionList getInstructionList() { 137 CodeAttribute ca = null; 138 if (instructions == null) { 139 ca = (CodeAttribute)getAttribute("Code"); 140 141 if (ca == null) { 142 return null; 143 } 144 145 byte[] byteCode = ca.getByteCode(); 146 147 instructions = new InstructionList(byteCode, 148 method.getConstantPool()); 149 instructions.setDeclaringMethod(this); 150 151 if (true) { 152 lineNumberTable = new LinkedList (); 156 157 LineNumberTableAttribute lnta = (LineNumberTableAttribute)ca.getAttribute(LineNumberTableAttribute.ATTRIBUTE_NAME); 158 159 if (lnta != null) { 160 List entries = lnta.getEntries(); 161 Iterator i = entries.iterator(); 162 while(i.hasNext()) { 163 LineNumberTableAttribute.Entry entry = 164 (LineNumberTableAttribute.Entry)i.next(); 165 166 Instruction ins = 167 instructions.instructionAtOffset(entry.getStartPc()); 168 169 lineNumberTable.add(new LNTableEntry(entry, ins)); 170 } 171 } 172 else { 173 } 175 } 176 177 178 this.exceptionTable = new LinkedList (); 179 List eTable = ca.getExceptionTable(); 180 181 if (eTable != null) { 182 Iterator i = eTable.iterator(); 183 while(i.hasNext()) { 184 CodeAttribute.ExceptionTableEntry entry = 185 (CodeAttribute.ExceptionTableEntry)i.next(); 186 187 Instruction start = 188 instructions.instructionAtOffset(entry.getStartPc()); 189 Instruction end = 190 instructions.instructionAtOffset(entry.getEndPc()); 191 Instruction handler = 192 instructions.instructionAtOffset(entry.getHandlerPc()); 193 194 this.exceptionTable.add(new ETEntry(entry, start, end, 195 handler)); 196 } 197 } 198 else { 199 } 201 } 202 203 return instructions; 204 } 205 206 207 217 TryBlock[] getTryBlocks() { 218 return null; 219 } 220 221 222 void addTryBlock(InstructionList tryBlock, String exceptionName, 224 Instruction handlerStart) { 225 } 226 void addTryBlock(TryBlock b) { 228 } 229 230 235 public JiapiClass getDeclaringClass() { 236 return declaringClass; 237 } 238 239 244 void setDeclaringClass(JiapiClass declaringClass) { 245 this.declaringClass = declaringClass; 246 } 247 248 249 259 public JiapiClass[] getParameterTypes() throws ClassNotFoundException { 260 String [] paramNames = getParameterTypeNames(); 261 JiapiClass[] types = new JiapiClass[paramNames.length]; 262 Loader loader = getDeclaringClass().getLoader(); 263 264 int i = 0; 265 try { 266 for (i = 0; i < paramNames.length; i++) { 267 types[i] = loader.loadClass(paramNames[i]); 268 } 269 } 270 catch(java.io.IOException ioe) { 271 throw new ClassNotFoundException (paramNames[i]); 272 } 273 274 return types; 275 } 276 277 283 public String [] getParameterTypeNames() { 284 return signature.getParameters(); 285 } 286 287 297 public JiapiClass[] getExceptionTypes() throws ClassNotFoundException { 298 String [] exceptionNames = getExceptionNames(); 299 JiapiClass[] types = new JiapiClass[exceptionNames.length]; 300 Loader loader = getDeclaringClass().getLoader(); 301 302 int i = 0; 303 try { 304 for (i = 0; i < exceptionNames.length; i++) { 305 types[i] = loader.loadClass(exceptionNames[i]); 306 } 307 } 308 catch(java.io.IOException ioe) { 309 throw new ClassNotFoundException (exceptionNames[i]); 310 } 311 312 return types; 313 } 314 315 321 public String [] getExceptionNames() { 322 ExceptionsAttribute a = 323 (ExceptionsAttribute)getAttribute("Exceptions"); 324 325 if (a == null) { 326 return new String [0]; 327 } 328 329 return a.getExceptionNames(); 330 } 331 332 339 public LocalVariable addLocalVariable(String type, String name) { 340 return null; 341 } 342 343 344 352 void copy(JiapiMethod source) { 353 } 355 356 359 public String toString() { 360 StringBuffer sb = new StringBuffer (); 361 String ms = Modifier.toString(getModifiers()); 362 sb.append(ms); 363 if (ms.length() > 0) { 364 sb.append(' '); 365 } 366 367 sb.append(getReturnType()); 368 sb.append(' '); 369 sb.append(getName()); 370 sb.append('('); 371 String [] params = getParameterTypeNames(); 372 for (int i = 0; i < params.length; i++) { 373 sb.append(params[i]); 374 if (i < params.length - 1) { 375 sb.append(','); 376 } 377 } 378 sb.append(')'); 379 380 String [] eNames = getExceptionNames(); 381 if (eNames.length > 0) { 382 sb.append(" throws "); 383 384 for(int i = 0; i < eNames.length; i++) { 385 sb.append(eNames[i]); 386 if (i < eNames.length - 1) { 387 sb.append(", "); 388 } 389 } 390 } 391 392 407 412 return sb.toString(); 413 } 414 415 416 417 420 private List getAttributes() { 421 return method.getAttributes(); 422 } 423 424 Method getMethod() { 425 return method; 426 } 427 428 429 432 Attribute getAttribute(String name) { 433 List l = method.getAttributes(); 434 Iterator i = l.iterator(); 435 436 while(i.hasNext()) { 437 Attribute a = (Attribute)i.next(); 438 if (a != null) { if (a.getName().equals(name)) { 440 return a; 441 } 442 } 443 } 444 445 return null; 446 } 447 448 449 void update() { 452 if (instructions != null) { 453 instructions.updateOffsets(); 454 updateBranchOffsets(); 456 457 CodeAttribute ca = (CodeAttribute)getAttribute("Code"); 458 ca.setByteCode(instructions.getBytes()); 459 460 updateMaxLocals(ca, instructions); 462 updateMaxStack(ca, instructions); 463 } 464 465 updateLineNumberTableOffsets(); 466 updateExceptionTableOffsets(); 467 } 468 469 470 private short updateMaxLocals(CodeAttribute ca, InstructionList il) { 475 short maxLocals = (short)(getParameterTypeNames().length); 477 478 482 LocalVariableTableAttribute lvta = (LocalVariableTableAttribute)getAttribute(LocalVariableTableAttribute.ATTRIBUTE_NAME); 483 484 if (lvta != null) { 486 maxLocals += lvta.getLocalVariables().size(); 487 } 488 489 490 short maxLocalsInInstructions = 0; 491 for(int i = 0; i < il.size(); i++) { 492 Instruction ins = il.get(i); 493 switch(ins.getOpcode()) { 494 case Opcodes.FLOAD_0: 495 case Opcodes.FSTORE_0: 496 case Opcodes.ILOAD_0: 497 case Opcodes.ISTORE_0: 498 case Opcodes.ALOAD_0: 499 case Opcodes.ASTORE_0: 500 if (maxLocals < 1) { 501 maxLocals = 1; 502 } 503 break; 504 505 case Opcodes.FLOAD_1: 506 case Opcodes.FSTORE_1: 507 case Opcodes.LSTORE_0: case Opcodes.LLOAD_0: 509 case Opcodes.DSTORE_0: case Opcodes.DLOAD_0: 511 case Opcodes.ILOAD_1: 512 case Opcodes.ISTORE_1: 513 case Opcodes.ALOAD_1: 514 case Opcodes.ASTORE_1: 515 if (maxLocals < 2) { 516 maxLocals = 2; 517 } 518 break; 519 520 case Opcodes.FLOAD_2: 521 case Opcodes.FSTORE_2: 522 case Opcodes.LSTORE_1: case Opcodes.LLOAD_1: 524 case Opcodes.DSTORE_1: case Opcodes.DLOAD_1: 526 case Opcodes.ILOAD_2: 527 case Opcodes.ISTORE_2: 528 case Opcodes.ALOAD_2: 529 case Opcodes.ASTORE_2: 530 if (maxLocals < 3) { 531 maxLocals = 3; 532 } 533 break; 534 535 case Opcodes.FLOAD_3: 536 case Opcodes.FSTORE_3: 537 case Opcodes.LSTORE_2: case Opcodes.LLOAD_2: 539 case Opcodes.DSTORE_2: case Opcodes.DLOAD_2: 541 case Opcodes.ILOAD_3: 542 case Opcodes.ISTORE_3: 543 case Opcodes.ALOAD_3: 544 case Opcodes.ASTORE_3: 545 if (maxLocals < 4) { 546 maxLocals = 4; 547 } 548 break; 549 550 case Opcodes.DSTORE_3: case Opcodes.DLOAD_3: 552 case Opcodes.LSTORE_3: case Opcodes.LLOAD_3: 554 if (maxLocals < 5) { 555 maxLocals = 5; 556 } 557 break; 558 559 case Opcodes.DSTORE: case Opcodes.DLOAD: 561 case Opcodes.LSTORE: case Opcodes.LLOAD: 563 byte[] bytes_l = ins.getBytes(); 564 int mloc_l = bytes_l[1]; 565 if (maxLocals < mloc_l + 1) { 566 maxLocals = (short)(mloc_l + 1); 567 } 568 break; 569 570 case Opcodes.FLOAD: 571 case Opcodes.FSTORE: 572 case Opcodes.ILOAD: 573 case Opcodes.ISTORE: 574 case Opcodes.ALOAD: 575 case Opcodes.ASTORE: 576 byte[] bytes = ins.getBytes(); 577 short mloc = bytes[1]; 578 if (maxLocals < mloc) { 579 maxLocals = mloc; 580 } 581 break; 582 } 583 } 584 585 maxLocals++; 586 ca.setMaxLocals(maxLocals); 587 588 return maxLocals; 589 } 590 591 592 596 private short updateMaxStack(CodeAttribute ca, InstructionList il) { 597 short maxStack = 0; 598 short su = 0; 599 600 if (il != null) { for(int i = 0; i < il.size(); i++) { 602 Instruction ins = il.get(i); 603 su += ins.stackUsage(); 604 605 if (su > maxStack) { 606 maxStack = su; 607 } 608 609 if (ins.getOpcode() == Opcodes.GETSTATIC || 613 ins.getOpcode() == Opcodes.GETFIELD) { 614 maxStack++; 615 } 616 617 618 619 } 620 621 ca.setMaxStack(maxStack); 622 } 623 624 return maxStack; 625 } 626 627 630 private void updateBranchOffsets() { 631 for(int i = 0; i < instructions.size(); i++) { 632 Instruction ins = instructions.get(i); 633 634 if (ins instanceof BranchInstruction) { 635 BranchInstruction bIns = (BranchInstruction)ins; 636 637 if (instructions.indexOf(bIns.getTarget()) != -1) { 641 int branchOffset = bIns.getOffset(); 642 int targetOffset = bIns.getTarget().getOffset(); 643 644 bIns.setTargetOffset(targetOffset - branchOffset); 646 } 647 else { 648 log.warn("Target instruction for branch was not found. This is most likely because branch-instruction was copied from some other instruction-list, and target was not copied. Branch offset is left as is."); 649 } 650 } 651 } 652 } 653 654 private void updateLineNumberTableOffsets() { 655 if (lineNumberTable != null) { 656 Iterator i = lineNumberTable.iterator(); 657 while(i.hasNext()) { 658 LNTableEntry entry = (LNTableEntry)i.next(); 659 entry.update(); 660 } 661 } 662 } 663 664 665 private void updateExceptionTableOffsets() { 666 if (exceptionTable != null) { 667 Iterator i = exceptionTable.iterator(); 668 while(i.hasNext()) { 669 ETEntry entry = (ETEntry)i.next(); 670 entry.update(); 671 } 672 } 673 } 674 675 public int getMaxLocals() { 676 CodeAttribute ca = (CodeAttribute)getAttribute("Code"); 677 if (ca == null) { 678 throw new NullPointerException ("No Code attribute found"); 679 } 680 ca.setByteCode(getInstructionList().getBytes()); 681 682 return updateMaxLocals(ca, getInstructionList()); 683 } 684 685 public int getMaxStack() { 686 CodeAttribute ca = (CodeAttribute)getAttribute("Code"); 687 689 return updateMaxStack(ca, getInstructionList()); 690 } 691 692 693 696 private class ETEntry { 697 private Instruction start; 698 private Instruction end; 699 private Instruction handler; 700 private CodeAttribute.ExceptionTableEntry entry; 701 702 ETEntry(CodeAttribute.ExceptionTableEntry entry, Instruction start, 703 Instruction end, Instruction handler) { 704 this.entry = entry; 707 this.start = start; 708 this.end = end; 709 this.handler = handler; 710 } 711 712 717 void update() { 718 entry.setStartPc(start.getOffset()); 724 entry.setEndPc(end.getOffset()); 725 entry.setHandlerPc(handler.getOffset()); 726 } 727 728 729 Instruction getStart() { 730 return start; 731 } 732 Instruction getEnd() { 733 return end; 734 } 735 Instruction getHandler() { 736 return handler; 737 } 738 } 739 740 741 746 public boolean isSynthetic() { 747 return (method.getAttribute(SyntheticAttribute.ATTRIBUTE_NAME) !=null); 748 } 749 } 750 | Popular Tags |