1 26 package com.yworks.yguard.obf.classfile; 27 28 import java.io.*; 29 import java.util.*; 30 import com.yworks.yguard.obf.*; 31 import java.lang.reflect.Modifier ; 32 import com.yworks.yguard.Conversion; 33 import com.yworks.yguard.ParseException; 34 35 43 public class ClassFile implements ClassConstants 44 { 45 public static final String SEP_REGULAR = "/"; 47 public static final String SEP_INNER = "$"; 48 public static final String LOG_DANGER_HEADER1 = "Methods are called which may break in obfuscated version at runtime."; 49 public static final String LOG_DANGER_HEADER2 = "Please review your source code to ensure that the dangerous methods are not intended"; 50 public static final String LOG_DANGER_HEADER3 = "to act on classes which have been obfuscated."; 51 private static final String [] SEMI_DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY = { 52 "forName(Ljava/lang/String;)Ljava/lang/Class;", 53 "forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", 54 }; 55 private static final String [] DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY = { 56 "forName(Ljava/lang/String;)Ljava/lang/Class;", 57 "forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", 58 "getDeclaredField(Ljava/lang/String;)Ljava/lang/reflect/Field;", 59 "getField(Ljava/lang/String;)Ljava/lang/reflect/Field;", 60 "getDeclaredMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", 61 "getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" 62 }; 63 private static final String LOG_DANGER_CLASS_PRE = " Your class "; 64 private static final String LOG_DANGER_CLASS_MID = " calls the java.lang.Class method "; 65 private static final String [] DANGEROUS_CLASSLOADER_SIMPLENAME_DESCRIPTOR_ARRAY = { 66 "defineClass(Ljava/lang/String;[BII)Ljava/lang/Class;", 67 "findLoadedClass(Ljava/lang/String;)Ljava/lang/Class;", 68 "findSystemClass(Ljava/lang/String;)Ljava/lang/Class;", 69 "loadClass(Ljava/lang/String;)Ljava/lang/Class;", 70 "loadClass(Ljava/lang/String;Z)Ljava/lang/Class;" 71 }; 72 private static final String LOG_DANGER_CLASSLOADER_PRE = " Your class "; 73 private static final String LOG_DANGER_CLASSLOADER_MID = " calls the java.lang.ClassLoader method "; 74 75 76 private int u4magic; 78 private int u2minorVersion; 79 private int u2majorVersion; 80 private ConstantPool constantPool; 81 private int u2accessFlags; 82 private int u2thisClass; 83 private int u2superClass; 84 private int u2interfacesCount; 85 private int u2interfaces[]; 86 private int u2fieldsCount; 87 private FieldInfo fields[]; 88 private int u2methodsCount; 89 private MethodInfo methods[]; 90 private int u2attributesCount; 91 private AttrInfo attributes[]; 92 93 private boolean isUnkAttrGone = false; 94 95 private static boolean writeIdString = false; 96 private static CpInfo cpIdString = null; 97 98 99 103 public static void defineIdString(String id) 104 { 105 if (id != null) { 106 writeIdString = true; 107 cpIdString = new Utf8CpInfo(id); 108 } else { 109 writeIdString = false; 110 cpIdString = null; 111 } 112 } 113 114 120 public static ClassFile create(DataInput din) throws java.io.IOException 121 { 122 if (din == null) throw new NullPointerException ("No input stream was provided."); 123 ClassFile cf = new ClassFile(); 124 cf.read(din); 125 return cf; 126 } 127 128 130 public static String [] parseDescriptor(String descriptor) 131 { 132 return parseDescriptor(descriptor, false); 133 } 134 135 137 public static String [] parseDescriptor(String descriptor, boolean isDisplay) 138 { 139 String [] names = null; 141 if (descriptor.charAt(0) != '(') 142 { 143 names = new String [1]; 144 names[0] = descriptor; 145 } 146 else 147 { 148 Vector namesVec = new Vector(); 150 descriptor = descriptor.substring(1); 151 String type = ""; 152 while (descriptor.length() > 0) 153 { 154 switch (descriptor.charAt(0)) 155 { 156 case '[': 157 type = type + "["; 158 descriptor = descriptor.substring(1); 159 break; 160 161 case 'B': 162 case 'C': 163 case 'D': 164 case 'F': 165 case 'I': 166 case 'J': 167 case 'S': 168 case 'Z': 169 case 'V': 170 namesVec.addElement(type + descriptor.substring(0, 1)); 171 descriptor = descriptor.substring(1); 172 type = ""; 173 break; 174 175 case ')': 176 descriptor = descriptor.substring(1); 177 break; 178 179 case 'L': 180 { 181 int pos = descriptor.indexOf(';') + 1; 182 namesVec.addElement(type + descriptor.substring(0, pos)); 183 descriptor = descriptor.substring(pos); 184 type = ""; 185 } 186 break; 187 188 default: 189 throw new IllegalArgumentException ("Illegal field or method descriptor: " + descriptor); 190 } 191 } 192 names = new String [namesVec.size()]; 193 for (int i = 0; i < names.length; i++) 194 { 195 names[i] = (String )namesVec.elementAt(i); 196 } 197 } 198 199 String [] translatedNames = new String [names.length]; 201 for (int i = 0; i < names.length; i++) 202 { 203 translatedNames[i] = translateType(names[i], isDisplay); 204 } 205 return translatedNames; 206 } 207 208 209 public static String translateType(String inName, boolean isDisplay) 210 { 211 String outName = null; 212 switch (inName.charAt(0)) 213 { 214 case '[': if (!isDisplay) 217 { 218 outName = translate(inName); 220 } 221 else 222 { 223 outName = translateType(inName.substring(1), true) + "[]"; 225 } 226 break; 227 228 case 'B': 229 outName = Byte.TYPE.getName(); 230 break; 231 232 case 'C': 233 outName = Character.TYPE.getName(); 234 break; 235 236 case 'D': 237 outName = Double.TYPE.getName(); 238 break; 239 240 case 'F': 241 outName = Float.TYPE.getName(); 242 break; 243 244 case 'I': 245 outName = Integer.TYPE.getName(); 246 break; 247 248 case 'J': 249 outName = Long.TYPE.getName(); 250 break; 251 252 case 'S': 253 outName = Short.TYPE.getName(); 254 break; 255 256 case 'Z': 257 outName = Boolean.TYPE.getName(); 258 break; 259 260 case 'V': 261 outName = Void.TYPE.getName(); 262 break; 263 264 case 'L': 265 { 266 int pos = inName.indexOf(';'); 267 outName = translate(inName.substring(1, inName.indexOf(';'))); 268 } 269 break; 270 271 default: 272 throw new IllegalArgumentException ("Illegal field or method name: " + inName); 273 } 274 return outName; 275 } 276 277 278 public static String translate(String name) 279 { 280 return name.replace('/', '.'); 281 } 282 283 284 private ClassFile() {} 287 288 private void read(DataInput din) throws java.io.IOException 290 { 291 u4magic = din.readInt(); 293 u2minorVersion = din.readUnsignedShort(); 294 u2majorVersion = din.readUnsignedShort(); 295 296 if (u4magic != MAGIC) 298 { 299 throw new IOException("Invalid magic number in class file."); 300 } 301 if (u2majorVersion > MAJOR_VERSION) 302 { 303 throw new IOException("Incompatible version number for class file format: " + u2majorVersion+"."+u2minorVersion); 304 } 305 306 307 int u2constantPoolCount = din.readUnsignedShort(); 308 CpInfo[] cpInfo = new CpInfo[u2constantPoolCount]; 309 for (int i = 1; i < u2constantPoolCount; i++) 312 { 313 cpInfo[i] = CpInfo.create(din); 314 if ((cpInfo[i] instanceof LongCpInfo) || 315 (cpInfo[i] instanceof DoubleCpInfo)) 316 { 317 i++; 318 } 319 } 320 constantPool = new ConstantPool(this, cpInfo); 321 322 u2accessFlags = din.readUnsignedShort(); 323 u2thisClass = din.readUnsignedShort(); 324 u2superClass = din.readUnsignedShort(); 325 u2interfacesCount = din.readUnsignedShort(); 326 u2interfaces = new int[u2interfacesCount]; 327 for (int i = 0; i < u2interfacesCount; i++) 328 { 329 u2interfaces[i] = din.readUnsignedShort(); 330 } 331 u2fieldsCount = din.readUnsignedShort(); 332 fields = new FieldInfo[u2fieldsCount]; 333 for (int i = 0; i < u2fieldsCount; i++) 334 { 335 fields[i] = FieldInfo.create(din, this); 336 } 337 u2methodsCount = din.readUnsignedShort(); 338 methods = new MethodInfo[u2methodsCount]; 339 for (int i = 0; i < u2methodsCount; i++) 340 { 341 methods[i] = MethodInfo.create(din, this); 342 } 343 u2attributesCount = din.readUnsignedShort(); 344 attributes = new AttrInfo[u2attributesCount]; 345 for (int i = 0; i < u2attributesCount; i++) 346 { 347 attributes[i] = AttrInfo.create(din, this); 348 } 349 } 350 351 public int getClassFileAccess(){ 352 return u2accessFlags; 353 } 354 355 public int getModifiers(){ 356 int mods = 0; 357 if ((u2accessFlags & 0x0001) == 0x0001) mods |= Modifier.PUBLIC; 358 if ((u2accessFlags & 0x0010) == 0x0010) mods |= Modifier.FINAL; 359 if ((u2accessFlags & 0x0200) == 0x0200) mods |= Modifier.INTERFACE; 360 if ((u2accessFlags & 0x0400) == 0x0400) mods |= Modifier.ABSTRACT; 361 return mods; 362 } 363 364 365 public String getName() 366 { 367 return toName(u2thisClass); 368 } 369 370 371 public String getSuper() 372 { 373 return (u2superClass == 0) ? null : toName(u2superClass); 375 } 376 377 378 public String [] getInterfaces() 379 { 380 String [] interfaces = new String [u2interfacesCount]; 381 for (int i = 0; i < u2interfacesCount; i++) 382 { 383 interfaces[i] = toName(u2interfaces[i]); 384 } 385 return interfaces; 386 } 387 388 private String toName(int u2index) 390 { 391 CpInfo classEntry = getCpEntry(u2index); 392 if (classEntry instanceof ClassCpInfo) 393 { 394 CpInfo nameEntry = getCpEntry(((ClassCpInfo)classEntry).getNameIndex()); 395 if (nameEntry instanceof Utf8CpInfo) 396 { 397 return ((Utf8CpInfo)nameEntry).getString(); 398 } 399 else 400 { 401 throw new ParseException("Inconsistent Constant Pool in class file."); 402 } 403 } 404 else 405 { 406 throw new ParseException("Inconsistent Constant Pool in class file."); 407 } 408 } 409 410 411 public Enumeration getMethodEnum() 412 { 413 Vector vec = new Vector(); 414 for (int i = 0; i < methods.length; i++) 415 { 416 vec.addElement(new Cons(new Cons(new Boolean (methods[i].isSynthetic()), 417 methods[i].getName()), 418 new Cons(methods[i].getDescriptor(), 419 new Integer (methods[i].getAccessFlags())))); 420 } 421 return vec.elements(); 422 } 423 424 425 public Enumeration getFieldEnum() 426 { 427 Vector vec = new Vector(); 428 for (int i = 0; i < fields.length; i++) 429 { 430 vec.addElement(new Cons(new Cons(new Boolean (fields[i].isSynthetic()), 431 fields[i].getName()), 432 new Cons(fields[i].getDescriptor(), 433 new Integer (fields[i].getAccessFlags())))); 434 } 435 return vec.elements(); 436 } 437 438 439 protected CpInfo getCpEntry(int cpIndex) 440 { 441 return constantPool.getCpEntry(cpIndex); 442 } 443 444 445 public String [] logDangerousMethods(boolean replaceClassNameStrings) 446 { 447 Vector warningVec = new Vector(); 448 449 for (Enumeration enumeration = constantPool.elements(); enumeration.hasMoreElements(); ) 452 { 453 Object o = enumeration.nextElement(); 454 if (o instanceof MethodrefCpInfo) 455 { 456 MethodrefCpInfo entry = (MethodrefCpInfo)o; 458 ClassCpInfo classEntry = (ClassCpInfo)getCpEntry(entry.getClassIndex()); 459 String className = ((Utf8CpInfo)getCpEntry(classEntry.getNameIndex())).getString(); 460 NameAndTypeCpInfo ntEntry = (NameAndTypeCpInfo)getCpEntry(entry.getNameAndTypeIndex()); 461 String name = ((Utf8CpInfo)getCpEntry(ntEntry.getNameIndex())).getString(); 462 String descriptor = ((Utf8CpInfo)getCpEntry(ntEntry.getDescriptorIndex())).getString(); 463 464 if (className.equals("java/lang/Class") && 466 Tools.isInArray(name + descriptor, DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY)) 467 { 468 if (replaceClassNameStrings){ 469 if (!Tools.isInArray(name+descriptor, SEMI_DANGEROUS_CLASS_SIMPLENAME_DESCRIPTOR_ARRAY)){ 470 String jMethod = Conversion.toJavaMethod(name, descriptor); 471 warningVec.addElement(LOG_DANGER_CLASS_PRE + Conversion.toJavaClass(getName()) + LOG_DANGER_CLASS_MID + jMethod); 472 } 473 } 474 } 475 else if (Tools.isInArray(name + descriptor, DANGEROUS_CLASSLOADER_SIMPLENAME_DESCRIPTOR_ARRAY)) 476 { 477 String jMethod = Conversion.toJavaMethod(name, descriptor); 478 warningVec.addElement(LOG_DANGER_CLASSLOADER_PRE + Conversion.toJavaClass(getName()) + LOG_DANGER_CLASSLOADER_MID + jMethod); 479 } else if ("class$(Ljava/lang/String;)Ljava/lang/Class;".equals(name+descriptor)){ 480 if (!replaceClassNameStrings){ 481 warningVec.addElement(LOG_DANGER_CLASS_PRE + Conversion.toJavaClass(getName()) +" seems to be using the '.class' construct!"); 482 } 483 } 484 } 485 } 486 487 String [] warnings = new String [warningVec.size()]; 489 for (int i = 0; i < warnings.length; i++) 490 { 491 warnings[i] = (String )warningVec.elementAt(i); 492 } 493 return warnings; 494 } 495 496 497 private static boolean hasHeader = false; 498 499 public static void resetDangerHeader() {hasHeader = false;} 500 public void logDangerousMethods(PrintWriter log, boolean replaceClassNameStrings) 501 { 502 String [] warnings = logDangerousMethods(replaceClassNameStrings); 504 if (warnings != null && warnings.length > 0) 505 { 506 if (!hasHeader) 507 { 508 log.println("<!-- WARNING"); 509 log.println(LOG_DANGER_HEADER1); 510 log.println(LOG_DANGER_HEADER2); 511 log.println(LOG_DANGER_HEADER3); 512 513 Logger logger = Logger.getInstance(); 514 logger.warning(LOG_DANGER_HEADER1+'\n'+ 515 LOG_DANGER_HEADER2+'\n'+ 516 LOG_DANGER_HEADER3+'\n'+ 517 "See the logfile for a list of these classes and methods."); 518 519 log.println("-->"); 520 hasHeader = true; 521 } 522 if (warnings.length > 0){ 523 log.println("<!--"); 524 for (int i = 0; i < warnings.length; i++) 525 { 526 log.println(" " + warnings[i]); 527 } 528 log.println("-->"); 529 } 530 } 531 } 532 533 534 public void markUtf8Refs(ConstantPool pool) 535 { 536 try 537 { 538 for (int i = 0; i < fields.length; i++) 540 { 541 fields[i].markUtf8Refs(pool); 542 } 543 for (int i = 0; i < methods.length; i++) 544 { 545 methods[i].markUtf8Refs(pool); } 547 for (int i = 0; i < attributes.length; i++) 548 { 549 attributes[i].markUtf8Refs(pool); } 551 552 for (Enumeration enumeration = pool.elements(); enumeration.hasMoreElements(); ) 554 { 555 Object o = enumeration.nextElement(); 556 if (o instanceof NameAndTypeCpInfo || 557 o instanceof ClassCpInfo || 558 o instanceof StringCpInfo) 559 { 560 ((CpInfo)o).markUtf8Refs(pool); 561 } 562 } 563 } 564 catch (ArrayIndexOutOfBoundsException e) 565 { 566 throw new ParseException("Inconsistent reference to constant pool."); 567 } 568 } 569 570 571 public void markNTRefs(ConstantPool pool) 572 { 573 try 574 { 575 for (Enumeration enumeration = pool.elements(); enumeration.hasMoreElements(); ) 577 { 578 Object o = enumeration.nextElement(); 579 if (o instanceof RefCpInfo) 580 { 581 ((CpInfo)o).markNTRefs(pool); 582 } 583 } 584 } 585 catch (ArrayIndexOutOfBoundsException e) 586 { 587 throw new ParseException("Inconsistent reference to constant pool."); 588 } 589 } 590 591 595 public void trimAttrsExcept(String [] extraAttrs) 596 { 597 String [] keepAttrs = REQUIRED_ATTRS; 599 if (extraAttrs != null && extraAttrs.length > 0) 600 { 601 String [] tmp = new String [keepAttrs.length + extraAttrs.length]; 602 System.arraycopy(keepAttrs, 0, tmp, 0, keepAttrs.length); 603 System.arraycopy(extraAttrs, 0, tmp, keepAttrs.length, extraAttrs.length); 604 keepAttrs = tmp; 605 } 606 607 for (int i = 0; i < fields.length; i++) 609 { 610 fields[i].trimAttrsExcept(keepAttrs); 611 } 612 for (int i = 0; i < methods.length; i++) 613 { 614 methods[i].trimAttrsExcept(keepAttrs); 615 } 616 for (int i = 0; i < attributes.length; i++) 617 { 618 if (Tools.isInArray(attributes[i].getAttrName(), keepAttrs)) 619 { 620 attributes[i].trimAttrsExcept(keepAttrs); 621 } 622 else 623 { 624 attributes[i] = null; 625 } 626 } 627 628 AttrInfo[] left = new AttrInfo[attributes.length]; 630 int j = 0; 631 for (int i = 0; i < attributes.length; i++) 632 { 633 if (attributes[i] != null) 634 { 635 left[j++] = attributes[i]; 636 } 637 } 638 attributes = new AttrInfo[j]; 639 System.arraycopy(left, 0, attributes, 0, j); 640 u2attributesCount = j; 641 642 isUnkAttrGone = true; 644 645 constantPool.updateRefCount(); 647 } 648 649 public Map getInnerClassModifiers() { 650 Map map = new HashMap(); 651 for (int i = 0; i < u2attributesCount; i++) 652 { 653 AttrInfo attrInfo = attributes[i]; 654 if (attrInfo instanceof InnerClassesAttrInfo) 655 { 656 InnerClassesInfo[] info = ((InnerClassesAttrInfo)attrInfo).getInfo(); 657 for (int j = 0; j < info.length; j++) 658 { 659 InnerClassesInfo ici = info[j]; 660 int index = info[j].getInnerNameIndex(); 661 if (index == 0){ continue; 663 } 664 CpInfo cpInfo = getCpEntry(info[j].getInnerNameIndex()); 665 if (cpInfo instanceof Utf8CpInfo) 666 { 667 Utf8CpInfo utf = (Utf8CpInfo)cpInfo; 668 String origClass = utf.getString(); 669 map.put(origClass, new Integer (ici.getModifiers())); 670 } 671 } 672 } 673 } 674 return map; 675 } 676 677 681 public void trimAttrs() {trimAttrsExcept(null);} 682 683 private boolean containsDotClassMethodReference(){ 684 for (Enumeration enumeration = constantPool.elements(); enumeration.hasMoreElements(); ) 687 { 688 Object o = enumeration.nextElement(); 689 if (o instanceof MethodrefCpInfo) 690 { 691 MethodrefCpInfo entry = (MethodrefCpInfo)o; 693 ClassCpInfo classEntry = (ClassCpInfo)getCpEntry(entry.getClassIndex()); 694 String className = ((Utf8CpInfo)getCpEntry(classEntry.getNameIndex())).getString(); 695 NameAndTypeCpInfo ntEntry = (NameAndTypeCpInfo)getCpEntry(entry.getNameAndTypeIndex()); 696 String name = ((Utf8CpInfo)getCpEntry(ntEntry.getNameIndex())).getString(); 697 698 if (name.equals("class$")){ 699 String descriptor = ((Utf8CpInfo)getCpEntry(ntEntry.getDescriptorIndex())).getString(); 700 if (descriptor.equals("(Ljava/lang/String;)Ljava/lang/Class;")){ 701 return true; 702 } 703 } 704 } 705 } 706 return false; 707 } 708 709 private boolean containsClassMethodReference(String cName, String des){ 710 for (Enumeration enumeration = constantPool.elements(); enumeration.hasMoreElements(); ) 713 { 714 Object o = enumeration.nextElement(); 715 if (o instanceof MethodrefCpInfo) 716 { 717 MethodrefCpInfo entry = (MethodrefCpInfo)o; 719 ClassCpInfo classEntry = (ClassCpInfo)getCpEntry(entry.getClassIndex()); 720 String className = ((Utf8CpInfo)getCpEntry(classEntry.getNameIndex())).getString(); 721 NameAndTypeCpInfo ntEntry = (NameAndTypeCpInfo)getCpEntry(entry.getNameAndTypeIndex()); 722 String name = ((Utf8CpInfo)getCpEntry(ntEntry.getNameIndex())).getString(); 723 String descriptor = ((Utf8CpInfo)getCpEntry(ntEntry.getDescriptorIndex())).getString(); 724 725 if (className.equals(cName) && (name+descriptor).equals(des)){ 727 return true; 728 } 729 } 730 } 731 return false; 732 } 733 734 735 public void remap(NameMapper nm, boolean replaceClassNameStrings, PrintWriter log) 736 { 737 String thisClassName = ((Utf8CpInfo)getCpEntry(((ClassCpInfo)getCpEntry(u2thisClass)).getNameIndex())).getString(); 740 741 final String [] attributesToKeep = nm.getAttrsToKeep(thisClassName); 743 if (attributesToKeep.length > 0) 744 { 745 trimAttrsExcept(attributesToKeep); 746 } 747 else 748 { 749 trimAttrs(); 750 } 751 752 for (int i = 0; i < u2attributesCount; i++) 754 { 755 AttrInfo attrInfo = attributes[i]; 756 if (attrInfo instanceof RuntimeVisibleAnnotationsAttrInfo){ 757 remapAnnotations((RuntimeVisibleAnnotationsAttrInfo)attrInfo, nm); 758 } else if (attrInfo instanceof InnerClassesAttrInfo) { 759 InnerClassesInfo[] info = ((InnerClassesAttrInfo)attrInfo).getInfo(); 761 for (int j = 0; j < info.length; j++) 762 { 763 CpInfo cpInfo = getCpEntry(info[j].getInnerNameIndex()); 765 if (cpInfo instanceof Utf8CpInfo) 766 { 767 Utf8CpInfo utf = (Utf8CpInfo)cpInfo; 769 String origClass = utf.getString(); 770 771 if (!origClass.equals("")) 773 { 774 ClassCpInfo innerClassInfo = (ClassCpInfo)getCpEntry(info[j].getInnerClassIndex()); 776 String innerClassName = ((Utf8CpInfo)getCpEntry(innerClassInfo.getNameIndex())).getString(); 777 778 String remapClass = nm.mapClass(innerClassName); 780 remapClass = remapClass.substring(remapClass.lastIndexOf('$') + 1); 781 int remapIndex = constantPool.remapUtf8To(remapClass, info[j].getInnerNameIndex()); 782 info[j].setInnerNameIndex(remapIndex); 783 } 784 } 785 } 786 } else if (attrInfo instanceof EnclosingMethodAttrInfo){ 787 EnclosingMethodAttrInfo eam = (EnclosingMethodAttrInfo) attrInfo; 788 789 CpInfo cpi = getCpEntry(eam.getClassIndex()); 791 if (cpi instanceof ClassCpInfo){ 792 ClassCpInfo ccpi = (ClassCpInfo) cpi; 793 cpi = getCpEntry(ccpi.getNameIndex()); 794 if (cpi instanceof Utf8CpInfo){ 795 Utf8CpInfo utf = (Utf8CpInfo) cpi; 796 String origClass = utf.getString(); 797 798 String remapClass = nm.mapClass(origClass); 800 801 if (eam.getNameAndTypeIndex() > 0) { 803 cpi = getCpEntry(eam.getNameAndTypeIndex()); 804 if (cpi instanceof NameAndTypeCpInfo){ 805 NameAndTypeCpInfo nameTypeInfo = (NameAndTypeCpInfo) cpi; 806 Utf8CpInfo refUtf = (Utf8CpInfo)getCpEntry(nameTypeInfo.getNameIndex()); 807 Utf8CpInfo descUtf = (Utf8CpInfo)getCpEntry(nameTypeInfo.getDescriptorIndex()); 808 String origMethodName = refUtf.getString(); 809 String origDescriptor = descUtf.getString(); 810 String remapRef = nm.mapMethod(origClass, origMethodName, origDescriptor); 811 String remapDesc = nm.mapDescriptor(descUtf.getString()); 812 eam.setNameAndTypeIndex(remapNT(refUtf, remapRef, descUtf, remapDesc, nameTypeInfo, eam.getNameAndTypeIndex())); 813 } 814 } 815 } 816 } 817 } else if (attrInfo instanceof SignatureAttrInfo){ 818 remapSignature(nm, (SignatureAttrInfo) attrInfo); 819 } else if (attrInfo instanceof SourceFileAttrInfo) { 820 SourceFileAttrInfo source = (SourceFileAttrInfo) attrInfo; 821 CpInfo cpInfo = getCpEntry(source.getSourceFileIndex()); 822 if (cpInfo instanceof Utf8CpInfo){ 823 Utf8CpInfo utf = (Utf8CpInfo) cpInfo; 824 String origName = utf.getString(); 825 if (origName != null && origName.length() > 0){ 826 String newName = nm.mapSourceFile(thisClassName, origName); 827 if (!origName.equals(newName)){ 828 if (newName == null || newName.length() < 1){ 829 AttrInfo[] newAttributes = new AttrInfo[attributes.length - 1]; 830 System.arraycopy(attributes, 0, newAttributes, 0, i); 831 if (newAttributes.length > i){ 832 System.arraycopy(attributes, i + 1, newAttributes, i, newAttributes.length - i); 833 } 834 attributes = newAttributes; 835 u2attributesCount--; 836 i--; 837 constantPool.decRefCount(source.getAttrNameIndex()); 838 utf.decRefCount(); 839 } else { 840 int remapIndex = constantPool.remapUtf8To(newName, source.getSourceFileIndex()); 841 source.setSourceFileIndex(remapIndex); 842 } 843 } 844 } 845 } 846 } 847 } 848 849 for (int i = 0; i < u2methodsCount; i++) 852 { 853 for (int j = 0; j < methods[i].u2attributesCount; j++) 854 { 855 final String methodName = methods[i].getName(); 856 final String descriptor = methods[i].getDescriptor(); 857 AttrInfo attrInfo = methods[i].attributes[j]; 858 859 if (attrInfo instanceof AnnotationDefaultAttrInfo){ 860 remapAnnotationDefault((AnnotationDefaultAttrInfo)attrInfo, nm); 861 } else if (attrInfo instanceof RuntimeVisibleAnnotationsAttrInfo){ 862 remapAnnotations((RuntimeVisibleAnnotationsAttrInfo)attrInfo, nm); 863 } else if (attrInfo instanceof RuntimeVisibleParameterAnnotationsAttrInfo){ 864 remapAnnotations((RuntimeVisibleParameterAnnotationsAttrInfo)attrInfo, nm); 865 } else if (attrInfo instanceof SignatureAttrInfo){ 866 remapSignature(nm, (SignatureAttrInfo) attrInfo); 867 } else if (attrInfo instanceof CodeAttrInfo) { 868 CodeAttrInfo codeAttrInfo = (CodeAttrInfo)attrInfo; 869 for (int k = 0; k < codeAttrInfo.u2attributesCount; k++) 870 { 871 AttrInfo innerAttrInfo = codeAttrInfo.attributes[k]; 872 if (innerAttrInfo instanceof LocalVariableTableAttrInfo) 873 { 874 LocalVariableTableAttrInfo lvtAttrInfo = (LocalVariableTableAttrInfo)innerAttrInfo; 875 LocalVariableInfo[] lvts = lvtAttrInfo.getLocalVariableTable(); 876 for (int m = 0; m < lvts.length; m++) 877 { 878 Utf8CpInfo nameUtf = (Utf8CpInfo)getCpEntry(lvts[m].getNameIndex()); 880 String remapName = nm.mapLocalVariable(thisClassName, methodName, descriptor, nameUtf.getString()); 881 if (remapName == null || remapName.length() < 1){ 882 constantPool.decRefCount(lvts[m].getNameIndex()); 883 constantPool.decRefCount(lvts[m].getDescriptorIndex()); 884 LocalVariableInfo[] newArray = new LocalVariableInfo[lvts.length - 1]; 885 System.arraycopy(lvts, 0, newArray, 0, m); 886 if (newArray.length > m ){ 887 System.arraycopy(lvts, m + 1, newArray, m, newArray.length - m); 888 } 889 lvts = newArray; 890 lvtAttrInfo.setLocalVariableTable(lvts); 891 m--; 892 } else { 893 lvts[m].setNameIndex(constantPool.remapUtf8To(remapName, lvts[m].getNameIndex())); 894 895 Utf8CpInfo descUtf = (Utf8CpInfo)getCpEntry(lvts[m].getDescriptorIndex()); 897 String remapDesc = nm.mapDescriptor(descUtf.getString()); 898 lvts[m].setDescriptorIndex(constantPool.remapUtf8To(remapDesc, lvts[m].getDescriptorIndex())); 899 } 900 } 901 } else if (innerAttrInfo instanceof LocalVariableTypeTableAttrInfo){ 902 LocalVariableTypeTableAttrInfo lvttAttrInfo = (LocalVariableTypeTableAttrInfo) innerAttrInfo; 903 LocalVariableTypeInfo[] lvts = lvttAttrInfo.getLocalVariableTypeTable(); 904 for (int m = 0; m < lvts.length; m++){ 905 Utf8CpInfo nameUtf = (Utf8CpInfo)getCpEntry(lvts[m].getNameIndex()); 907 String remapName = nm.mapLocalVariable(thisClassName, methodName, descriptor, nameUtf.getString()); 908 if (remapName == null || remapName.length() < 1){ 909 constantPool.decRefCount(lvts[m].getNameIndex()); 910 constantPool.decRefCount(lvts[m].getSignatureIndex()); 911 LocalVariableTypeInfo[] newArray = new LocalVariableTypeInfo[lvts.length - 1]; 912 System.arraycopy(lvts, 0, newArray, 0, m); 913 if (newArray.length > m ){ 914 System.arraycopy(lvts, m + 1, newArray, m, newArray.length - m); 915 } 916 lvts = newArray; 917 lvttAttrInfo.setLocalVariableTypeTable(lvts); 918 m--; 919 } else { 920 lvts[m].setNameIndex(constantPool.remapUtf8To(remapName, lvts[m].getNameIndex())); 921 922 Utf8CpInfo signatureUtf = (Utf8CpInfo)getCpEntry(lvts[m].getSignatureIndex()); 924 String remapSig = nm.mapSignature(signatureUtf.getString()); 925 lvts[m].setSignatureIndex(constantPool.remapUtf8To(remapSig, lvts[m].getSignatureIndex())); 926 } 927 } 928 } else if (innerAttrInfo instanceof LineNumberTableAttrInfo) { 929 LineNumberTableAttrInfo ltai = (LineNumberTableAttrInfo) innerAttrInfo; 930 if (!nm.mapLineNumberTable(thisClassName, methodName, descriptor, ltai)){ 931 AttrInfo[] newAtt = new AttrInfo[codeAttrInfo.u2attributesCount - 1]; 932 System.arraycopy(codeAttrInfo.attributes, 0, newAtt, 0, k); 933 if (newAtt.length > k ){ 934 System.arraycopy(codeAttrInfo.attributes, k + 1, newAtt, k, newAtt.length - k); 935 } 936 codeAttrInfo.attributes = newAtt; 937 codeAttrInfo.u2attributesCount--; 938 k--; 939 } 940 } 941 } 942 } 943 } 944 } 945 946 for (int i = 0; i < u2fieldsCount; i++) 948 { 949 FieldInfo field = fields[i]; 951 Utf8CpInfo nameUtf = (Utf8CpInfo)getCpEntry(field.getNameIndex()); 952 if (!field.isSynthetic() || nameUtf.getString().startsWith("class$")) 953 { 954 String remapName = nm.mapField(thisClassName, nameUtf.getString()); 955 field.setNameIndex(constantPool.remapUtf8To(remapName, field.getNameIndex())); 956 } 957 958 for (int j = 0; j < field.u2attributesCount; j++){ 959 AttrInfo attrInfo = field.attributes[j]; 960 if (attrInfo instanceof RuntimeVisibleAnnotationsAttrInfo){ 961 remapAnnotations((RuntimeVisibleAnnotationsAttrInfo)attrInfo, nm); 962 } else if (attrInfo instanceof SignatureAttrInfo){ 963 remapSignature(nm, (SignatureAttrInfo) attrInfo); 964 } 965 } 966 967 Utf8CpInfo descUtf = (Utf8CpInfo)getCpEntry(field.getDescriptorIndex()); 969 String remapDesc = nm.mapDescriptor(descUtf.getString()); 970 field.setDescriptorIndex(constantPool.remapUtf8To(remapDesc, field.getDescriptorIndex())); 971 } 972 for (int i = 0; i < u2methodsCount; i++) 973 { 974 MethodInfo method = methods[i]; 976 Utf8CpInfo descUtf = (Utf8CpInfo)getCpEntry(method.getDescriptorIndex()); 977 if (!method.isSynthetic()) 978 { 979 Utf8CpInfo nameUtf = (Utf8CpInfo)getCpEntry(method.getNameIndex()); 980 String remapName = nm.mapMethod(thisClassName, nameUtf.getString(), descUtf.getString()); 981 method.setNameIndex(constantPool.remapUtf8To(remapName, method.getNameIndex())); 982 } 983 984 String remapDesc = nm.mapDescriptor(descUtf.getString()); 986 method.setDescriptorIndex(constantPool.remapUtf8To(remapDesc, method.getDescriptorIndex())); 987 } 988 989 if (replaceClassNameStrings && nm instanceof ClassTree) 991 { 996 this.replaceConstantPoolStrings((ClassTree)nm); 997 } 998 999 int currentCpLength = constantPool.length(); for (int i = 0; i < currentCpLength; i++) 1002 { 1003 CpInfo cpInfo = getCpEntry(i); 1004 if (cpInfo != null) 1005 { 1006 if (cpInfo instanceof RefCpInfo) 1010 { 1011 ClassCpInfo classInfo = (ClassCpInfo)getCpEntry(((RefCpInfo)cpInfo).getClassIndex()); 1013 Utf8CpInfo classUtf = (Utf8CpInfo)getCpEntry(classInfo.getNameIndex()); 1014 String className = classUtf.getString(); 1015 1016 int ntIndex = ((RefCpInfo)cpInfo).getNameAndTypeIndex(); 1018 1019 NameAndTypeCpInfo nameTypeInfo = (NameAndTypeCpInfo)getCpEntry(ntIndex); 1020 Utf8CpInfo refUtf = (Utf8CpInfo)getCpEntry(nameTypeInfo.getNameIndex()); 1021 Utf8CpInfo descUtf = (Utf8CpInfo)getCpEntry(nameTypeInfo.getDescriptorIndex()); 1022 1023 String remapRef; 1025 if (cpInfo instanceof FieldrefCpInfo) 1026 { 1027 remapRef = nm.mapField(className, refUtf.getString()); 1028 1029 if (refUtf.getString().startsWith("class$")) 1032 { 1033 if (!replaceClassNameStrings){ 1034 String internalClassName = refUtf.getString().substring(6); 1035 String realClassName = internalClassName.replace('$', '.'); 1036 internalClassName = internalClassName.replace('$','/'); 1037 String map = nm.mapClass(internalClassName); 1038 if (map != null && !internalClassName.equals(map)){ 1039 String warning = realClassName + 1040 " shouldn't be obfuscated: it is most likely referenced as " + realClassName + ".class from " + 1041 Conversion.toJavaClass(thisClassName); 1042 Logger.getInstance().warning(warning); 1043 log.println("<!-- WARNING: " + warning + " -->"); 1044 } 1045 } 1046 } 1047 } 1048 else 1049 { 1050 remapRef = nm.mapMethod(className, refUtf.getString(), descUtf.getString()); 1051 } 1052 String remapDesc = nm.mapDescriptor(descUtf.getString()); 1053 ((RefCpInfo)cpInfo).setNameAndTypeIndex(remapNT(refUtf, remapRef, descUtf, remapDesc, nameTypeInfo, ((RefCpInfo)cpInfo).getNameAndTypeIndex())); 1054 } 1055 } 1056 } 1057 1058 for (int i = 0; i < constantPool.length(); i++) 1060 { 1061 CpInfo cpInfo = getCpEntry(i); 1062 if (cpInfo != null) 1063 { 1064 if (cpInfo instanceof ClassCpInfo) 1066 { 1067 ClassCpInfo classInfo = (ClassCpInfo)cpInfo; 1068 Utf8CpInfo utf = (Utf8CpInfo)getCpEntry(classInfo.getNameIndex()); 1069 String remapClass = nm.mapClass(utf.getString()); 1070 int remapIndex = constantPool.remapUtf8To(remapClass, classInfo.getNameIndex()); 1071 classInfo.setNameIndex(remapIndex); 1072 } 1073 } 1074 } 1075 } 1076 1077 private void remapAnnotationDefault(AnnotationDefaultAttrInfo annotationDefault, NameMapper nm){ 1078 remapElementValue(annotationDefault.elementValue, nm); 1079 } 1080 1081 private void remapAnnotations(RuntimeVisibleAnnotationsAttrInfo annotation, NameMapper nm){ 1082 final AnnotationInfo[] annotations = annotation.getAnnotations(); 1083 if (annotations != null){ 1084 for (int i = 0; i < annotations.length; i++){ 1085 remapAnnotation(annotations[i], nm); 1086 } 1087 } 1088 } 1089 1090 private void remapAnnotations(RuntimeVisibleParameterAnnotationsAttrInfo annotation, NameMapper nm){ 1091 final ParameterAnnotationInfo[] annotations = annotation.getParameterAnnotations(); 1092 if (annotations != null){ 1093 for (int i = 0; i < annotations.length; i++){ 1094 final ParameterAnnotationInfo info = annotations[i]; 1095 final AnnotationInfo[] a = info.getAnnotations(); 1096 if (a != null) { 1097 for (int j = 0; j < a.length; j++){ 1098 remapAnnotation(a[j], nm); 1099 } 1100 } 1101 } 1102 } 1103 } 1104 1105 private void remapAnnotation(AnnotationInfo annotation, NameMapper nm){ 1106 CpInfo info = getCpEntry(annotation.u2typeIndex); 1107 if (info instanceof Utf8CpInfo){ 1108 Utf8CpInfo utf = (Utf8CpInfo) info; 1109 String s = utf.getString(); 1110 if (s.length() > 2 && s.charAt(0) == 'L' && s.charAt(s.length() - 1) == ';'){ 1111 String fqn = s.substring(1, s.length() - 1); 1112 String newFqn = nm.mapClass(fqn); 1113 if (!fqn.equals(newFqn)){ 1114 annotation.u2typeIndex = constantPool.remapUtf8To('L' + newFqn + ';', annotation.u2typeIndex); 1115 } 1116 final ElementValuePairInfo[] evp = annotation.getElementValuePairs(); 1117 if (evp != null){ 1118 for (int i = 0; i < evp.length; i++){ 1119 final ElementValuePairInfo elementValuePair = evp[i]; 1120 utf = (Utf8CpInfo) getCpEntry(elementValuePair.u2ElementNameIndex); 1121 String remapName = nm.mapAnnotationField(fqn, utf.getString()); 1122 if (!remapName.equals(utf.getString())){ 1123 elementValuePair.u2ElementNameIndex = constantPool.remapUtf8To(remapName, elementValuePair.u2ElementNameIndex); 1124 } 1125 final ElementValueInfo elementValue = elementValuePair.elementValue; 1126 remapElementValue(elementValue, nm); 1127 } 1128 } 1129 } 1130 } 1131 } 1132 1133 private void remapElementValue(ElementValueInfo elementValue, NameMapper nm){ 1134 switch (elementValue.u1Tag) 1135 { 1136 case 'B': 1137 case 'C': 1138 case 'D': 1139 case 'F': 1140 case 'I': 1141 case 'J': 1142 case 'S': 1143 case 'Z': 1144 case 's': 1145 break; 1147 case 'e': 1148 { 1150 Utf8CpInfo utf = (Utf8CpInfo) getCpEntry(elementValue.u2typeNameIndex); 1151 String name = utf.getString(); 1152 if (name.length() > 22 & name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';'){ 1153 name = name.substring(1, name.length() - 1); 1154 String remapName = 'L' + nm.mapClass(name) + ';'; 1155 elementValue.u2typeNameIndex = constantPool.remapUtf8To(remapName, elementValue.u2typeNameIndex); 1156 } 1157 } 1158 break; 1160 case 'c': 1161 { 1162 Utf8CpInfo utf = (Utf8CpInfo) getCpEntry(elementValue.u2cpIndex); 1163 String name = utf.getString(); 1164 if (name.length() > 22 & name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';'){ 1165 name = name.substring(1, name.length() - 1); 1166 String remapName = 'L' + nm.mapClass(name) + ';'; 1167 elementValue.u2cpIndex = constantPool.remapUtf8To(remapName, elementValue.u2cpIndex); 1168 } 1169 } 1170 break; 1171 case '@': 1172 remapAnnotation(elementValue.nestedAnnotation, nm); 1173 break; 1174 case '[': 1175 for (int j = 0; j < elementValue.arrayValues.length; j++) 1176 { 1177 final ElementValueInfo evi = elementValue.arrayValues[j]; 1178 remapElementValue(evi, nm); 1179 } 1180 break; 1181 default: 1182 throw new RuntimeException ("Unknown type tag in annotation!"); 1183 } 1184 } 1185 1186 private void remapSignature(NameMapper nm, SignatureAttrInfo signature){ 1187 CpInfo cpInfo = getCpEntry(signature.getSignatureIndex()); 1188 if (cpInfo instanceof Utf8CpInfo){ 1189 Utf8CpInfo utf = (Utf8CpInfo) cpInfo; 1190 String sig = utf.getString(); 1191 String remapSignature = nm.mapSignature(sig); 1192 if (!sig.equals(remapSignature)){ 1193 int remapIndex = constantPool.remapUtf8To(remapSignature, signature.getSignatureIndex()); 1194 signature.setSignatureIndex(remapIndex); 1195 } 1196 } 1197 } 1198 1199 private int remapNT(Utf8CpInfo refUtf, String remapRef, Utf8CpInfo descUtf, String remapDesc, NameAndTypeCpInfo nameTypeInfo, int nameAndTypeIndex){ 1200 if (!remapRef.equals(refUtf.getString()) || 1204 !remapDesc.equals(descUtf.getString())) 1205 { 1206 NameAndTypeCpInfo newNameTypeInfo; 1208 if (nameTypeInfo.getRefCount() == 1) 1209 { 1210 newNameTypeInfo = nameTypeInfo; 1211 } 1212 else 1213 { 1214 newNameTypeInfo = (NameAndTypeCpInfo)nameTypeInfo.clone(); 1216 1217 ((CpInfo)getCpEntry(newNameTypeInfo.getNameIndex())).incRefCount(); 1219 ((CpInfo)getCpEntry(newNameTypeInfo.getDescriptorIndex())).incRefCount(); 1220 1221 nameAndTypeIndex = constantPool.addEntry(newNameTypeInfo); 1224 1225 newNameTypeInfo.incRefCount(); 1227 nameTypeInfo.decRefCount(); 1228 } 1229 1230 newNameTypeInfo.setNameIndex(constantPool.remapUtf8To(remapRef, newNameTypeInfo.getNameIndex())); 1232 newNameTypeInfo.setDescriptorIndex(constantPool.remapUtf8To(remapDesc, newNameTypeInfo.getDescriptorIndex())); 1233 } 1234 return nameAndTypeIndex; 1235 } 1236 1237 1241 private void replaceConstantPoolStrings(ClassTree ct){ 1242 for (Enumeration enumeration = constantPool.elements(); enumeration.hasMoreElements();){ 1243 CpInfo cpi = (CpInfo) enumeration.nextElement(); 1244 if (cpi instanceof Utf8CpInfo){ 1245 Utf8CpInfo ui = (Utf8CpInfo) cpi; 1246 String s = ui.getString(); 1247 boolean jikes = false; 1248 if (s.length()>5 && s.startsWith("[L") && s.endsWith(";")){ 1249 s = s.substring(2, s.length()-1); 1250 jikes = true; 1251 } 1252 if (s.length()>2 && Character.isJavaIdentifierPart(s.charAt(s.length()-1)) && 1253 s.indexOf(' ')<0 && s.indexOf('.')>0){ 1254 Cl cl = ct.findClassForName(s); 1255 if (cl != null){ 1256 if (!cl.getFullInName().equals(cl.getFullOutName())){ 1257 if (jikes){ 1258 ui.setString("[L"+cl.getFullOutName().replace('/','.')+";"); 1259 } else { 1260 ui.setString(cl.getFullOutName().replace('/','.')); 1261 } 1262 } 1263 } 1264 } 1265 } 1266 } 1267 } 1268 1269 1270 public void write(DataOutput dout) throws java.io.IOException 1271 { 1272 if (dout == null) throw new NullPointerException ("No output stream was provided."); 1273 dout.writeInt(u4magic); 1274 dout.writeShort(u2minorVersion); 1275 dout.writeShort(u2majorVersion); 1276 dout.writeShort(constantPool.length() + (writeIdString ? 1 : 0)); 1277 for (Enumeration enumeration = constantPool.elements(); enumeration.hasMoreElements(); ) 1278 { 1279 CpInfo cpInfo = (CpInfo)enumeration.nextElement(); 1280 if (cpInfo != null) 1281 { 1282 cpInfo.write(dout); 1283 } 1284 } 1285 if (writeIdString) { 1286 cpIdString.write(dout); 1287 } 1288 dout.writeShort(u2accessFlags); 1289 dout.writeShort(u2thisClass); 1290 dout.writeShort(u2superClass); 1291 dout.writeShort(u2interfacesCount); 1292 for (int i = 0; i < u2interfacesCount; i++) 1293 { 1294 dout.writeShort(u2interfaces[i]); 1295 } 1296 dout.writeShort(u2fieldsCount); 1297 for (int i = 0; i < u2fieldsCount; i++) 1298 { 1299 fields[i].write(dout); 1300 } 1301 dout.writeShort(u2methodsCount); 1302 for (int i = 0; i < u2methodsCount; i++) 1303 { 1304 methods[i].write(dout); 1305 } 1306 dout.writeShort(u2attributesCount); 1307 for (int i = 0; i < u2attributesCount; i++) 1308 { 1309 attributes[i].write(dout); 1310 } 1311 } 1312 1313 1314 public void dump(PrintWriter pw) 1315 { 1316 pw.println("_____________________________________________________________________"); 1317 pw.println("CLASS: " + getName()); 1318 pw.println("Magic: " + Integer.toHexString(u4magic)); 1319 pw.println("Minor version: " + Integer.toHexString(u2minorVersion)); 1320 pw.println("Major version: " + Integer.toHexString(u2majorVersion)); 1321 pw.println(); 1322 pw.println("CP length: " + Integer.toHexString(constantPool.length())); 1323 for (int i = 0; i < constantPool.length(); i++) 1324 { 1325 CpInfo cpInfo = (CpInfo)constantPool.getCpEntry(i); 1326 if (cpInfo != null) 1327 { 1328 cpInfo.dump(pw, this, i); 1329 } 1330 } 1331 pw.println("Access: " + Integer.toHexString(u2accessFlags)); 1332 pw.println("This class: " + getName()); 1333 pw.println("Superclass: " + getSuper()); 1334 pw.println("Interfaces count: " + Integer.toHexString(u2interfacesCount)); 1335 for (int i = 0; i < u2interfacesCount; i++) 1336 { 1337 CpInfo info = getCpEntry(u2interfaces[i]); 1338 if (info == null) 1339 { 1340 pw.println(" Interface " + Integer.toHexString(i) + ": (null)"); 1341 } 1342 else 1343 { 1344 pw.println(" Interface " + Integer.toHexString(i) + ": " + ((Utf8CpInfo)getCpEntry(((ClassCpInfo)info).getNameIndex())).getString()); 1345 } 1346 } 1347 pw.println("Fields count: " + Integer.toHexString(u2fieldsCount)); 1348 for (int i = 0; i < u2fieldsCount; i++) 1349 { 1350 ClassItemInfo info = fields[i]; 1351 if (info == null) 1352 { 1353 pw.println(" Field " + Integer.toHexString(i) + ": (null)"); 1354 } 1355 else 1356 { 1357 pw.println(" Field " + Integer.toHexString(i) + ": " + ((Utf8CpInfo)getCpEntry(info.getNameIndex())).getString() + " " + ((Utf8CpInfo)getCpEntry(info.getDescriptorIndex())).getString()); 1358 } 1359 pw.println(" Attrs count: " + Integer.toHexString(info.u2attributesCount)); 1360 for (int j = 0; j < info.u2attributesCount; j++) 1361 { 1362 pw.println(info.attributes[j]); 1363 } 1364 } 1365 pw.println("Methods count: " + Integer.toHexString(u2methodsCount)); 1366 for (int i = 0; i < u2methodsCount; i++) 1367 { 1368 ClassItemInfo info = methods[i]; 1369 if (info == null) 1370 { 1371 pw.println(" Method " + Integer.toHexString(i) + ": (null)"); 1372 } 1373 else 1374 { 1375 pw.println(" Method " + Integer.toHexString(i) + ": " + ((Utf8CpInfo)getCpEntry(info.getNameIndex())).getString() + " " + ((Utf8CpInfo)getCpEntry(info.getDescriptorIndex())).getString() + " " + Integer.toHexString(info.getAccessFlags())); 1376 } 1377 pw.println(" Attrs count: " + Integer.toHexString(info.u2attributesCount)); 1378 for (int j = 0; j < info.u2attributesCount; j++) 1379 { 1380 if (info.attributes[j] instanceof CodeAttrInfo){ 1381 pw.println(info.attributes[j]); 1382 CodeAttrInfo cai = (CodeAttrInfo) info.attributes[j]; 1383 for (int k = 0; k < cai.u2attributesCount; k++){ 1384 pw.println(cai.attributes[k]); 1385 } 1386 } else { 1387 pw.println(info.attributes[j]); 1388 } 1389 } 1390 } 1391 pw.println("Attrs count: " + Integer.toHexString(u2attributesCount)); 1392 for (int i = 0; i < u2attributesCount; i++) 1393 { 1394 pw.println(attributes[i]); 1395 } 1396 } 1397 1398} 1399 | Popular Tags |