1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later, 9 * or the Apache License Version 2.0. 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 */ 16 17 package javassist; 18 19 import java.io.BufferedOutputStream; 20 import java.io.ByteArrayOutputStream; 21 import java.io.DataOutputStream; 22 import java.io.File; 23 import java.io.FileOutputStream; 24 import java.io.IOException; 25 import java.io.OutputStream; 26 import java.net.URL; 27 import java.security.ProtectionDomain; 28 import java.util.Collection; 29 30 import javassist.bytecode.ClassFile; 31 import javassist.bytecode.Descriptor; 32 import javassist.bytecode.Opcode; 33 import javassist.expr.ExprEditor; 34 35 /* Note: 36 * 37 * This class is an abstract class and several methods just return null 38 * or throw an exception. Those methods are overridden in subclasses 39 * of this class. Read the source code of CtClassType if you are 40 * interested in the implementation of Javassist. 41 * 42 * Subclasses of CtClass are CtClassType, CtPrimitiveType, and CtArray. 43 */ 44 45 /** 46 * An instance of <code>CtClass</code> represents a class. 47 * It is obtained from <code>ClassPool</code>. 48 * 49 * @see ClassPool#get(String) 50 */ 51 public abstract class CtClass { 52 protected String qualifiedName; 53 54 /** 55 * If the value of this field is not null, then all class 56 * files modified by Javassist are saved under the directory 57 * specified by this variable. For example, if the value is 58 * <code>"./debug"</code>, then all class files are saved 59 * there. The directory name must not end with a directory 60 * separator such as <code>/</code>. 61 * 62 * <p>The default value is null. 63 * 64 * @see #debugWriteFile(String) 65 * @since 3.16 66 */ 67 public static String debugDump = null; 68 69 /** 70 * The version number of this release. 71 */ 72 public static final String version = "3.24.1-GA"; 73 74 /** 75 * Prints the version number and the copyright notice. 76 * 77 * <p>The following command invokes this method: 78 * 79 * <pre>java -jar javassist.jar</pre> 80 */ main(String[] args)81 public static void main(String[] args) { 82 System.out.println("Javassist version " + CtClass.version); 83 System.out.println("Copyright (C) 1999-2018 Shigeru Chiba." 84 + " All Rights Reserved."); 85 } 86 87 static final String javaLangObject = "java.lang.Object"; 88 89 /** 90 * The <code>CtClass</code> object representing 91 * the <code>boolean</code> type. 92 */ 93 public static CtClass booleanType; 94 95 /** 96 * The <code>CtClass</code> object representing 97 * the <code>char</code> type. 98 */ 99 public static CtClass charType; 100 101 /** 102 * The <code>CtClass</code> object representing 103 * the <code>byte</code> type. 104 */ 105 public static CtClass byteType; 106 107 /** 108 * The <code>CtClass</code> object representing 109 * the <code>short</code> type. 110 */ 111 public static CtClass shortType; 112 113 /** 114 * The <code>CtClass</code> object representing 115 * the <code>int</code> type. 116 */ 117 public static CtClass intType; 118 119 /** 120 * The <code>CtClass</code> object representing 121 * the <code>long</code> type. 122 */ 123 public static CtClass longType; 124 125 /** 126 * The <code>CtClass</code> object representing 127 * the <code>float</code> type. 128 */ 129 public static CtClass floatType; 130 131 /** 132 * The <code>CtClass</code> object representing 133 * the <code>double</code> type. 134 */ 135 public static CtClass doubleType; 136 137 /** 138 * The <code>CtClass</code> object representing 139 * the <code>void</code> type. 140 */ 141 public static CtClass voidType; 142 143 static CtClass[] primitiveTypes; 144 145 static { 146 primitiveTypes = new CtClass[9]; 147 148 booleanType = 149 new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean", 150 "booleanValue", "()Z", Opcode.IRETURN, 151 Opcode.T_BOOLEAN, 1); 152 primitiveTypes[0] = booleanType; 153 154 charType = new CtPrimitiveType("char", 'C', "java.lang.Character", 155 "charValue", "()C", Opcode.IRETURN, 156 Opcode.T_CHAR, 1); 157 primitiveTypes[1] = charType; 158 159 byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte", 160 "byteValue", "()B", Opcode.IRETURN, 161 Opcode.T_BYTE, 1); 162 primitiveTypes[2] = byteType; 163 164 shortType = new CtPrimitiveType("short", 'S', "java.lang.Short", 165 "shortValue", "()S", Opcode.IRETURN, 166 Opcode.T_SHORT, 1); 167 primitiveTypes[3] = shortType; 168 169 intType = new CtPrimitiveType("int", 'I', "java.lang.Integer", 170 "intValue", "()I", Opcode.IRETURN, 171 Opcode.T_INT, 1); 172 primitiveTypes[4] = intType; 173 174 longType = new CtPrimitiveType("long", 'J', "java.lang.Long", 175 "longValue", "()J", Opcode.LRETURN, 176 Opcode.T_LONG, 2); 177 primitiveTypes[5] = longType; 178 179 floatType = new CtPrimitiveType("float", 'F', "java.lang.Float", 180 "floatValue", "()F", Opcode.FRETURN, 181 Opcode.T_FLOAT, 1); 182 primitiveTypes[6] = floatType; 183 184 doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double", 185 "doubleValue", "()D", Opcode.DRETURN, 186 Opcode.T_DOUBLE, 2); 187 primitiveTypes[7] = doubleType; 188 189 voidType = new CtPrimitiveType("void", 'V', "java.lang.Void", 190 null, null, Opcode.RETURN, 0, 0); 191 primitiveTypes[8] = voidType; 192 } 193 CtClass(String name)194 protected CtClass(String name) { 195 qualifiedName = name; 196 } 197 198 /** 199 * Converts the object to a string. 200 */ 201 @Override toString()202 public String toString() { 203 StringBuffer buf = new StringBuffer(getClass().getName()); 204 buf.append("@"); 205 buf.append(Integer.toHexString(hashCode())); 206 buf.append("["); 207 extendToString(buf); 208 buf.append("]"); 209 return buf.toString(); 210 } 211 212 /** 213 * Implemented in subclasses to add to the {@link #toString()} result. 214 * Subclasses should put a space before each token added to the buffer. 215 */ extendToString(StringBuffer buffer)216 protected void extendToString(StringBuffer buffer) { 217 buffer.append(getName()); 218 } 219 220 /** 221 * Returns a <code>ClassPool</code> for this class. 222 */ getClassPool()223 public ClassPool getClassPool() { return null; } 224 225 /** 226 * Returns a class file for this class. 227 * 228 * <p>This method is not available if <code>isFrozen()</code> 229 * is true. 230 */ getClassFile()231 public ClassFile getClassFile() { 232 checkModify(); 233 return getClassFile2(); 234 } 235 236 /** 237 * Returns a class file for this class (read only). 238 * Normal applications do not need calling this method. Use 239 * <code>getClassFile()</code>. 240 * 241 * <p>The <code>ClassFile</code> object obtained by this method 242 * is read only. Changes to this object might not be reflected 243 * on a class file generated by <code>toBytecode()</code>, 244 * <code>toClass()</code>, etc. 245 * 246 * <p>This method is available even if <code>isFrozen()</code> 247 * is true. However, if the class is frozen, it might be also 248 * pruned. 249 * 250 * @see CtClass#getClassFile() 251 * @see CtClass#isFrozen() 252 * @see CtClass#prune() 253 */ getClassFile2()254 public ClassFile getClassFile2() { return null; } 255 256 /** 257 * Undocumented method. Do not use; internal-use only. 258 */ getAccessorMaker()259 public javassist.compiler.AccessorMaker getAccessorMaker() { 260 return null; 261 } 262 263 /** 264 * Returns the uniform resource locator (URL) of the class file. 265 */ getURL()266 public URL getURL() throws NotFoundException { 267 throw new NotFoundException(getName()); 268 } 269 270 /** 271 * Returns true if the definition of the class has been modified. 272 */ isModified()273 public boolean isModified() { return false; } 274 275 /** 276 * Returns true if the class has been loaded or written out 277 * and thus it cannot be modified any more. 278 * 279 * @see #defrost() 280 * @see #detach() 281 */ isFrozen()282 public boolean isFrozen() { return true; } 283 284 /** 285 * Makes the class frozen. 286 * 287 * @see #isFrozen() 288 * @see #defrost() 289 * @since 3.6 290 */ freeze()291 public void freeze() {} 292 293 /* Note: this method is overridden by CtClassType 294 */ checkModify()295 void checkModify() throws RuntimeException { 296 if (isFrozen()) 297 throw new RuntimeException(getName() + " class is frozen"); 298 299 // isModified() must return true after this method is invoked. 300 } 301 302 /** 303 * Defrosts the class so that the class can be modified again. 304 * 305 * <p>To avoid changes that will be never reflected, 306 * the class is frozen to be unmodifiable if it is loaded or 307 * written out. This method should be called only in a case 308 * that the class will be reloaded or written out later again. 309 * 310 * <p>If <code>defrost()</code> will be called later, pruning 311 * must be disallowed in advance. 312 * 313 * @see #isFrozen() 314 * @see #stopPruning(boolean) 315 * @see #detach() 316 */ defrost()317 public void defrost() { 318 throw new RuntimeException("cannot defrost " + getName()); 319 } 320 321 /** 322 * Returns <code>true</code> if this object represents a primitive 323 * Java type: boolean, byte, char, short, int, long, float, double, 324 * or void. 325 */ isPrimitive()326 public boolean isPrimitive() { return false; } 327 328 /** 329 * Returns <code>true</code> if this object represents an array type. 330 */ isArray()331 public boolean isArray() { 332 return false; 333 } 334 335 /** 336 * If this object represents an array, this method returns the component 337 * type of the array. Otherwise, it returns <code>null</code>. 338 */ getComponentType()339 public CtClass getComponentType() throws NotFoundException { 340 return null; 341 } 342 343 /** 344 * Returns <code>true</code> if this class extends or implements 345 * <code>clazz</code>. It also returns <code>true</code> if 346 * this class is the same as <code>clazz</code>. 347 */ subtypeOf(CtClass clazz)348 public boolean subtypeOf(CtClass clazz) throws NotFoundException { 349 return this == clazz || getName().equals(clazz.getName()); 350 } 351 352 /** 353 * Obtains the fully-qualified name of the class. 354 */ getName()355 public String getName() { return qualifiedName; } 356 357 /** 358 * Obtains the not-qualified class name. 359 */ getSimpleName()360 public final String getSimpleName() { 361 String qname = qualifiedName; 362 int index = qname.lastIndexOf('.'); 363 if (index < 0) 364 return qname; 365 return qname.substring(index + 1); 366 } 367 368 /** 369 * Obtains the package name. It may be <code>null</code>. 370 */ getPackageName()371 public final String getPackageName() { 372 String qname = qualifiedName; 373 int index = qname.lastIndexOf('.'); 374 if (index < 0) 375 return null; 376 return qname.substring(0, index); 377 } 378 379 /** 380 * Sets the class name 381 * 382 * @param name fully-qualified name 383 */ setName(String name)384 public void setName(String name) { 385 checkModify(); 386 if (name != null) 387 qualifiedName = name; 388 } 389 390 /** 391 * Returns the generic signature of the class. 392 * 393 * <p>The generics of Java is implemented by the erasure technique. 394 * After compilation, all type parameters are dropped off from the 395 * main part of a class file. However, for reflection, the type 396 * parameters are encoded into generic signatures and attached 397 * to a class file. 398 * 399 * @return null if the generic signature is not included. 400 * @see javassist.bytecode.SignatureAttribute#toClassSignature(String) 401 * @see CtMember#getGenericSignature() 402 * @since 3.17 403 */ getGenericSignature()404 public String getGenericSignature() { return null; } 405 406 /** 407 * Sets the generic signature of the class. 408 * 409 * <p>The generics of Java is implemented by the erasure technique. 410 * After compilation, all type parameters are dropped off from the 411 * main part of a class file. However, for reflection, the type 412 * parameters must be encoded into generic signatures and attached 413 * to a class file. 414 * 415 * <p>For example, 416 * 417 * <pre>class List<T> { 418 * T value; 419 * T get() { return value; } 420 * void set(T v) { value = v; } 421 * } 422 * </pre> 423 * 424 * <p>this class is generated by the following code: 425 * 426 * <pre> 427 * ClassPool pool = ClassPool.getDefault(); 428 * CtClass cc = pool.makeClass("List"); 429 * CtClass objectClass = pool.get(CtClass.javaLangObject); 430 * ClassSignature cs = new ClassSignature( 431 * new TypeParameter[] { new TypeParameter("T") }); 432 * cc.setGenericSignature(cs.encode()); // <T:Ljava/lang/Object;>Ljava/lang/Object; 433 * 434 * CtField f = new CtField(objClass, "value", cc); 435 * TypeVariable tvar = new TypeVariable("T"); 436 * f.setGenericSignature(tvar.encode()); // TT; 437 * cc.addField(f); 438 * 439 * CtMethod m = CtNewMethod.make("public Object get(){return value;}", cc); 440 * MethodSignature ms = new MethodSignature(null, null, tvar, null); 441 * m.setGenericSignature(ms.encode()); // ()TT; 442 * cc.addMethod(m); 443 * 444 * CtMethod m2 = CtNewMethod.make("public void set(Object v){value = v;}", cc); 445 * MethodSignature ms2 = new MethodSignature(null, new Type[] { tvar }, 446 * new BaseType("void"), null); 447 * m2.setGenericSignature(ms2.encode()); // (TT;)V; 448 * cc.addMethod(m2); 449 * 450 * cc.writeFile(); 451 * </pre> 452 * 453 * <p>The generated class file is equivalent to the following: 454 * 455 * <pre>class List { 456 * Object value; 457 * Object get() { return value; } 458 * void set(Object v) { value = v; } 459 * }</pre> 460 * 461 * <p>but it includes generic signatures for the class, the field, 462 * and the methods so that the type variable <code>T</code> can be 463 * accessible through reflection. 464 * 465 * <p><code>MethodSignature</code> is a utility class. You can directly 466 * pass the signature string to the <code>setGenericSignature</code> method. 467 * For the specification of the signatures, see Section 4.7.9.1 <i>Signatures</i> 468 * of The Java Virtual Machine Specification (Java SE 8). 469 * 470 * @param sig a generic signature. 471 * @see javassist.bytecode.SignatureAttribute.ClassSignature#encode() 472 * @see javassist.bytecode.SignatureAttribute.MethodSignature#encode() 473 * @see CtMember#setGenericSignature(String) 474 * @since 3.17 475 */ setGenericSignature(String sig)476 public void setGenericSignature(String sig) { checkModify(); } 477 478 /** 479 * Substitutes <code>newName</code> for all occurrences of a class 480 * name <code>oldName</code> in the class file. 481 * 482 * @param oldName replaced class name 483 * @param newName substituted class name 484 */ replaceClassName(String oldName, String newName)485 public void replaceClassName(String oldName, String newName) { 486 checkModify(); 487 } 488 489 /** 490 * Changes class names appearing in the class file according to the 491 * given <code>map</code>. 492 * 493 * <p>All the class names appearing in the class file are tested 494 * with <code>map</code> to determine whether each class name is 495 * replaced or not. Thus this method can be used for collecting 496 * all the class names in the class file. To do that, first define 497 * a subclass of <code>ClassMap</code> so that <code>get()</code> 498 * records all the given parameters. Then, make an instance of 499 * that subclass as an empty hash-table. Finally, pass that instance 500 * to this method. After this method finishes, that instance would 501 * contain all the class names appearing in the class file. 502 * 503 * @param map the hashtable associating replaced class names 504 * with substituted names. 505 */ replaceClassName(ClassMap map)506 public void replaceClassName(ClassMap map) { 507 checkModify(); 508 } 509 510 /** 511 * Returns a collection of the names of all the classes 512 * referenced in this class. 513 * That collection includes the name of this class. 514 * 515 * <p>This method may return <code>null</code>. 516 * 517 * @return a <code>Collection<String></code> object. 518 */ getRefClasses()519 public synchronized Collection<String> getRefClasses() { 520 ClassFile cf = getClassFile2(); 521 if (cf != null) { 522 ClassMap cm = new ClassMap() { 523 /** default serialVersionUID */ 524 private static final long serialVersionUID = 1L; 525 @Override 526 public String put(String oldname, String newname) { 527 return put0(oldname, newname); 528 } 529 @Override 530 public String get(Object jvmClassName) { 531 String n = toJavaName((String)jvmClassName); 532 put0(n, n); 533 return null; 534 } 535 536 @Override 537 public void fix(String name) {} 538 }; 539 cf.getRefClasses(cm); 540 return cm.values(); 541 } 542 return null; 543 } 544 545 /** 546 * Determines whether this object represents a class or an interface. 547 * It returns <code>true</code> if this object represents an interface. 548 */ isInterface()549 public boolean isInterface() { 550 return false; 551 } 552 553 /** 554 * Determines whether this object represents an annotation type. 555 * It returns <code>true</code> if this object represents an annotation type. 556 * 557 * @since 3.2 558 */ isAnnotation()559 public boolean isAnnotation() { 560 return false; 561 } 562 563 /** 564 * Determines whether this object represents an enum. 565 * It returns <code>true</code> if this object represents an enum. 566 * 567 * @since 3.2 568 */ isEnum()569 public boolean isEnum() { 570 return false; 571 } 572 573 /** 574 * Returns the modifiers for this class, encoded in an integer. 575 * For decoding, use <code>javassist.Modifier</code>. 576 * 577 * <p>If the class is a static nested class (a.k.a. static inner class), 578 * the returned modifiers include <code>Modifier.STATIC</code>. 579 * 580 * @see Modifier 581 */ getModifiers()582 public int getModifiers() { 583 return 0; 584 } 585 586 /** 587 * Returns true if the class has the specified annotation type. 588 * 589 * @param annotationType the annotation type. 590 * @return <code>true</code> if the annotation is found, otherwise <code>false</code>. 591 * @since 3.11 592 */ hasAnnotation(Class<?> annotationType)593 public boolean hasAnnotation(Class<?> annotationType) { 594 return hasAnnotation(annotationType.getName()); 595 } 596 597 /** 598 * Returns true if the class has the specified annotation type. 599 * 600 * @param annotationTypeName the name of annotation type. 601 * @return <code>true</code> if the annotation is found, otherwise <code>false</code>. 602 * @since 3.21 603 */ hasAnnotation(String annotationTypeName)604 public boolean hasAnnotation(String annotationTypeName) { 605 return false; 606 } 607 608 /** 609 * Returns the annotation if the class has the specified annotation type. 610 * For example, if an annotation <code>@Author</code> is associated 611 * with this class, an <code>Author</code> object is returned. 612 * The member values can be obtained by calling methods on 613 * the <code>Author</code> object. 614 * 615 * @param clz the annotation type. 616 * @return the annotation if found, otherwise <code>null</code>. 617 * @since 3.11 618 */ getAnnotation(Class<?> clz)619 public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { 620 return null; 621 } 622 623 /** 624 * Returns the annotations associated with this class. 625 * For example, if an annotation <code>@Author</code> is associated 626 * with this class, the returned array contains an <code>Author</code> 627 * object. The member values can be obtained by calling methods on 628 * the <code>Author</code> object. 629 * 630 * @return an array of annotation-type objects. 631 * @see CtMember#getAnnotations() 632 * @since 3.1 633 */ getAnnotations()634 public Object[] getAnnotations() throws ClassNotFoundException { 635 return new Object[0]; 636 } 637 638 /** 639 * Returns the annotations associated with this class. 640 * This method is equivalent to <code>getAnnotations()</code> 641 * except that, if any annotations are not on the classpath, 642 * they are not included in the returned array. 643 * 644 * @return an array of annotation-type objects. 645 * @see #getAnnotations() 646 * @see CtMember#getAvailableAnnotations() 647 * @since 3.3 648 */ getAvailableAnnotations()649 public Object[] getAvailableAnnotations(){ 650 return new Object[0]; 651 } 652 653 /** 654 * Returns an array of nested classes declared in the class. 655 * Nested classes are inner classes, anonymous classes, local classes, 656 * and static nested classes. This simply calls <code>getNestedClasses()</code>. 657 * 658 * @see #getNestedClasses() 659 * @since 3.15 660 */ getDeclaredClasses()661 public CtClass[] getDeclaredClasses() throws NotFoundException { 662 return getNestedClasses(); 663 } 664 665 /** 666 * Returns an array of nested classes declared in the class. 667 * Nested classes are inner classes, anonymous classes, local classes, 668 * and static nested classes. 669 * 670 * @since 3.2 671 */ getNestedClasses()672 public CtClass[] getNestedClasses() throws NotFoundException { 673 return new CtClass[0]; 674 } 675 676 /** 677 * Sets the modifiers. 678 * 679 * <p>If the class is a nested class, this method also modifies 680 * the class declaring that nested class (i.e. the enclosing 681 * class is modified). 682 * 683 * @param mod modifiers encoded by 684 * <code>javassist.Modifier</code> 685 * @see Modifier 686 */ setModifiers(int mod)687 public void setModifiers(int mod) { 688 checkModify(); 689 } 690 691 /** 692 * Determines whether the class directly or indirectly extends 693 * the given class. If this class extends a class A and 694 * the class A extends a class B, then subclassof(B) returns true. 695 * 696 * <p>This method returns true if the given class is identical to 697 * the class represented by this object. 698 */ subclassOf(CtClass superclass)699 public boolean subclassOf(CtClass superclass) { 700 return false; 701 } 702 703 /** 704 * Obtains the class object representing the superclass of the 705 * class. 706 * It returns null if this object represents the 707 * <code>java.lang.Object</code> class and thus it does not have 708 * the super class. 709 * 710 * <p>If this object represents an interface, this method 711 * always returns the <code>java.lang.Object</code> class. 712 * To obtain the super interfaces 713 * extended by that interface, call <code>getInterfaces()</code>. 714 */ getSuperclass()715 public CtClass getSuperclass() throws NotFoundException { 716 return null; 717 } 718 719 /** 720 * Changes a super class unless this object represents an interface. 721 * The new super class must be compatible with the old one; for example, 722 * it should inherit from the old super class. 723 * 724 * <p>If this object represents an interface, this method is equivalent 725 * to <code>addInterface()</code>; it appends <code>clazz</code> to 726 * the list of the super interfaces extended by that interface. 727 * Note that an interface can extend multiple super interfaces. 728 * 729 * @see #replaceClassName(String, String) 730 * @see #replaceClassName(ClassMap) 731 */ setSuperclass(CtClass clazz)732 public void setSuperclass(CtClass clazz) throws CannotCompileException { 733 checkModify(); 734 } 735 736 /** 737 * Obtains the class objects representing the interfaces implemented 738 * by the class or, if this object represents an interface, the interfaces 739 * extended by that interface. 740 */ getInterfaces()741 public CtClass[] getInterfaces() throws NotFoundException { 742 return new CtClass[0]; 743 } 744 745 /** 746 * Sets implemented interfaces. If this object represents an interface, 747 * this method sets the interfaces extended by that interface. 748 * 749 * @param list a list of the <code>CtClass</code> objects 750 * representing interfaces, or 751 * <code>null</code> if the class implements 752 * no interfaces. 753 */ setInterfaces(CtClass[] list)754 public void setInterfaces(CtClass[] list) { 755 checkModify(); 756 } 757 758 /** 759 * Adds an interface. 760 * 761 * @param anInterface the added interface. 762 */ addInterface(CtClass anInterface)763 public void addInterface(CtClass anInterface) { 764 checkModify(); 765 } 766 767 /** 768 * If this class is a member class or interface of another class, 769 * then the class enclosing this class is returned. 770 * 771 * @return null if this class is a top-level class or an anonymous class. 772 */ getDeclaringClass()773 public CtClass getDeclaringClass() throws NotFoundException { 774 return null; 775 } 776 777 /** 778 * Returns the immediately enclosing method of this class. 779 * This method works only with JDK 1.5 or later. 780 * 781 * @return null if this class is not a local class or an anonymous 782 * class. 783 * @deprecated The enclosing method might be a constructor. 784 * Use {@link #getEnclosingBehavior()}. 785 * @see #getEnclosingBehavior() 786 */ 787 @Deprecated getEnclosingMethod()788 public final CtMethod getEnclosingMethod() throws NotFoundException { 789 CtBehavior b = getEnclosingBehavior(); 790 if (b == null) 791 return null; 792 else if (b instanceof CtMethod) 793 return (CtMethod)b; 794 else 795 throw new NotFoundException(b.getLongName() + " is enclosing " + getName()); 796 } 797 798 /** 799 * Returns the immediately enclosing method of this class. 800 * It might be not a method but a constructor. 801 * This method works only with JDK 1.5 or later. 802 * 803 * @return null if this class is not a local class or an anonymous 804 * class. 805 */ getEnclosingBehavior()806 public CtBehavior getEnclosingBehavior() throws NotFoundException { 807 return null; 808 } 809 810 /** 811 * Makes a new public nested class. If this method is called, 812 * the <code>CtClass</code>, which encloses the nested class, is modified 813 * since a class file includes a list of nested classes. 814 * 815 * <p>The current implementation only supports a static nested class. 816 * <code>isStatic</code> must be true. 817 * 818 * @param name the simple name of the nested class. 819 * @param isStatic true if the nested class is static. 820 */ makeNestedClass(String name, boolean isStatic)821 public CtClass makeNestedClass(String name, boolean isStatic) { 822 throw new RuntimeException(getName() + " is not a class"); 823 } 824 825 /** 826 * Returns an array containing <code>CtField</code> objects 827 * representing all the non-private fields of the class. 828 * That array includes non-private fields inherited from the 829 * superclasses. 830 */ getFields()831 public CtField[] getFields() { return new CtField[0]; } 832 833 /** 834 * Returns the field with the specified name. The returned field 835 * may be a private field declared in a super class or interface. 836 */ getField(String name)837 public CtField getField(String name) throws NotFoundException { 838 return getField(name, null); 839 } 840 841 /** 842 * Returns the field with the specified name and type. The returned field 843 * may be a private field declared in a super class or interface. 844 * Unlike Java, the JVM allows a class to have 845 * multiple fields with the same name but different types. 846 * 847 * @param name the field name. 848 * @param desc the type descriptor of the field. It is available by 849 * {@link CtField#getSignature()}. 850 * @see CtField#getSignature() 851 */ getField(String name, String desc)852 public CtField getField(String name, String desc) throws NotFoundException { 853 throw new NotFoundException(name); 854 } 855 856 /** 857 * @return null if the specified field is not found. 858 */ getField2(String name, String desc)859 CtField getField2(String name, String desc) { return null; } 860 861 /** 862 * Gets all the fields declared in the class. The inherited fields 863 * are not included. 864 * 865 * <p>Note: the result does not include inherited fields. 866 */ getDeclaredFields()867 public CtField[] getDeclaredFields() { return new CtField[0]; } 868 869 /** 870 * Retrieves the field with the specified name among the fields 871 * declared in the class. 872 * 873 * <p>Note: this method does not search the super classes. 874 */ getDeclaredField(String name)875 public CtField getDeclaredField(String name) throws NotFoundException { 876 throw new NotFoundException(name); 877 } 878 879 /** 880 * Retrieves the field with the specified name and type among the fields 881 * declared in the class. Unlike Java, the JVM allows a class to have 882 * multiple fields with the same name but different types. 883 * 884 * <p>Note: this method does not search the super classes. 885 * 886 * @param name the field name. 887 * @param desc the type descriptor of the field. It is available by 888 * {@link CtField#getSignature()}. 889 * @see CtField#getSignature() 890 */ getDeclaredField(String name, String desc)891 public CtField getDeclaredField(String name, String desc) throws NotFoundException { 892 throw new NotFoundException(name); 893 } 894 895 /** 896 * Gets all the constructors and methods declared in the class. 897 */ getDeclaredBehaviors()898 public CtBehavior[] getDeclaredBehaviors() { 899 return new CtBehavior[0]; 900 } 901 902 /** 903 * Returns an array containing <code>CtConstructor</code> objects 904 * representing all the non-private constructors of the class. 905 */ getConstructors()906 public CtConstructor[] getConstructors() { 907 return new CtConstructor[0]; 908 } 909 910 /** 911 * Returns the constructor with the given signature, 912 * which is represented by a character string 913 * called method descriptor. 914 * For details of the method descriptor, see the JVM specification 915 * or <code>javassist.bytecode.Descriptor</code>. 916 * 917 * @param desc method descriptor 918 * @see javassist.bytecode.Descriptor 919 */ getConstructor(String desc)920 public CtConstructor getConstructor(String desc) 921 throws NotFoundException 922 { 923 throw new NotFoundException("no such constructor"); 924 } 925 926 /** 927 * Gets all the constructors declared in the class. 928 * 929 * @see javassist.CtConstructor 930 */ getDeclaredConstructors()931 public CtConstructor[] getDeclaredConstructors() { 932 return new CtConstructor[0]; 933 } 934 935 /** 936 * Returns a constructor receiving the specified parameters. 937 * 938 * @param params parameter types. 939 */ getDeclaredConstructor(CtClass[] params)940 public CtConstructor getDeclaredConstructor(CtClass[] params) 941 throws NotFoundException 942 { 943 String desc = Descriptor.ofConstructor(params); 944 return getConstructor(desc); 945 } 946 947 /** 948 * Gets the class initializer (static constructor) 949 * declared in the class. 950 * This method returns <code>null</code> if 951 * no class initializer is not declared. 952 * 953 * @see #makeClassInitializer() 954 * @see javassist.CtConstructor 955 */ getClassInitializer()956 public CtConstructor getClassInitializer() { 957 return null; 958 } 959 960 /** 961 * Returns an array containing <code>CtMethod</code> objects 962 * representing all the non-private methods of the class. 963 * That array includes non-private methods inherited from the 964 * superclasses. 965 */ getMethods()966 public CtMethod[] getMethods() { 967 return new CtMethod[0]; 968 } 969 970 /** 971 * Returns the method with the given name and signature. 972 * The returned method may be declared in a super class. 973 * The method signature is represented by a character string 974 * called method descriptor, 975 * which is defined in the JVM specification. 976 * 977 * @param name method name 978 * @param desc method descriptor 979 * @see CtBehavior#getSignature() 980 * @see javassist.bytecode.Descriptor 981 */ getMethod(String name, String desc)982 public CtMethod getMethod(String name, String desc) 983 throws NotFoundException 984 { 985 throw new NotFoundException(name); 986 } 987 988 /** 989 * Gets all methods declared in the class. The inherited methods 990 * are not included. 991 * 992 * @see javassist.CtMethod 993 */ getDeclaredMethods()994 public CtMethod[] getDeclaredMethods() { 995 return new CtMethod[0]; 996 } 997 998 /** 999 * Retrieves the method with the specified name and parameter types 1000 * among the methods declared in the class. 1001 * 1002 * <p>Note: this method does not search the superclasses. 1003 * 1004 * @param name method name 1005 * @param params parameter types 1006 * @see javassist.CtMethod 1007 */ getDeclaredMethod(String name, CtClass[] params)1008 public CtMethod getDeclaredMethod(String name, CtClass[] params) 1009 throws NotFoundException 1010 { 1011 throw new NotFoundException(name); 1012 } 1013 1014 /** 1015 * Retrieves methods with the specified name among the methods 1016 * declared in the class. Multiple methods with different parameters 1017 * may be returned. 1018 * 1019 * <p>Note: this method does not search the superclasses.</p> 1020 * 1021 * @param name method name. 1022 * @since 3.19 1023 */ getDeclaredMethods(String name)1024 public CtMethod[] getDeclaredMethods(String name) throws NotFoundException { 1025 throw new NotFoundException(name); 1026 } 1027 1028 /** 1029 * Retrieves the method with the specified name among the methods 1030 * declared in the class. If there are multiple methods with 1031 * the specified name, then this method returns one of them. 1032 * 1033 * <p>Note: this method does not search the superclasses. 1034 * 1035 * @see javassist.CtMethod 1036 */ getDeclaredMethod(String name)1037 public CtMethod getDeclaredMethod(String name) throws NotFoundException { 1038 throw new NotFoundException(name); 1039 } 1040 1041 /** 1042 * Makes an empty class initializer (static constructor). 1043 * If the class already includes a class initializer, 1044 * this method returns it. 1045 * 1046 * @see #getClassInitializer() 1047 */ makeClassInitializer()1048 public CtConstructor makeClassInitializer() 1049 throws CannotCompileException 1050 { 1051 throw new CannotCompileException("not a class"); 1052 } 1053 1054 /** 1055 * Adds a constructor. To add a class initializer (static constructor), 1056 * call <code>makeClassInitializer()</code>. 1057 * 1058 * @see #makeClassInitializer() 1059 */ addConstructor(CtConstructor c)1060 public void addConstructor(CtConstructor c) 1061 throws CannotCompileException 1062 { 1063 checkModify(); 1064 } 1065 1066 /** 1067 * Removes a constructor declared in this class. 1068 * 1069 * @param c removed constructor. 1070 * @throws NotFoundException if the constructor is not found. 1071 */ removeConstructor(CtConstructor c)1072 public void removeConstructor(CtConstructor c) throws NotFoundException { 1073 checkModify(); 1074 } 1075 1076 /** 1077 * Adds a method. 1078 */ addMethod(CtMethod m)1079 public void addMethod(CtMethod m) throws CannotCompileException { 1080 checkModify(); 1081 } 1082 1083 /** 1084 * Removes a method declared in this class. 1085 * 1086 * @param m removed method. 1087 * @throws NotFoundException if the method is not found. 1088 */ removeMethod(CtMethod m)1089 public void removeMethod(CtMethod m) throws NotFoundException { 1090 checkModify(); 1091 } 1092 1093 /** 1094 * Adds a field. 1095 * 1096 * <p>The <code>CtField</code> belonging to another 1097 * <code>CtClass</code> cannot be directly added to this class. 1098 * Only a field created for this class can be added. 1099 * 1100 * @see javassist.CtField#CtField(CtField,CtClass) 1101 */ addField(CtField f)1102 public void addField(CtField f) throws CannotCompileException { 1103 addField(f, (CtField.Initializer)null); 1104 } 1105 1106 /** 1107 * Adds a field with an initial value. 1108 * 1109 * <p>The <code>CtField</code> belonging to another 1110 * <code>CtClass</code> cannot be directly added to this class. 1111 * Only a field created for this class can be added. 1112 * 1113 * <p>The initial value is given as an expression written in Java. 1114 * Any regular Java expression can be used for specifying the initial 1115 * value. The followings are examples. 1116 * 1117 * <pre> 1118 * cc.addField(f, "0") // the initial value is 0. 1119 * cc.addField(f, "i + 1") // i + 1. 1120 * cc.addField(f, "new Point()"); // a Point object. 1121 * </pre> 1122 * 1123 * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>. 1124 * The type of <code>f</code> is <code>CtField</code>. 1125 * 1126 * <p>Note: do not change the modifier of the field 1127 * (in particular, do not add or remove <code>static</code> 1128 * to/from the modifier) 1129 * after it is added to the class by <code>addField()</code>. 1130 * 1131 * @param init an expression for the initial value. 1132 * 1133 * @see javassist.CtField.Initializer#byExpr(String) 1134 * @see javassist.CtField#CtField(CtField,CtClass) 1135 */ addField(CtField f, String init)1136 public void addField(CtField f, String init) 1137 throws CannotCompileException 1138 { 1139 checkModify(); 1140 } 1141 1142 /** 1143 * Adds a field with an initial value. 1144 * 1145 * <p>The <code>CtField</code> belonging to another 1146 * <code>CtClass</code> cannot be directly added to this class. 1147 * Only a field created for this class can be added. 1148 * 1149 * <p>For example, 1150 * 1151 * <pre> 1152 * CtClass cc = ...; 1153 * addField(new CtField(CtClass.intType, "i", cc), 1154 * CtField.Initializer.constant(1)); 1155 * </pre> 1156 * 1157 * <p>This code adds an <code>int</code> field named "i". The 1158 * initial value of this field is 1. 1159 * 1160 * @param init specifies the initial value of the field. 1161 * 1162 * @see javassist.CtField#CtField(CtField,CtClass) 1163 */ addField(CtField f, CtField.Initializer init)1164 public void addField(CtField f, CtField.Initializer init) 1165 throws CannotCompileException 1166 { 1167 checkModify(); 1168 } 1169 1170 /** 1171 * Removes a field declared in this class. 1172 * 1173 * @param f removed field. 1174 * @throws NotFoundException if the field is not found. 1175 */ removeField(CtField f)1176 public void removeField(CtField f) throws NotFoundException { 1177 checkModify(); 1178 } 1179 1180 /** 1181 * Obtains an attribute with the given name. 1182 * If that attribute is not found in the class file, this 1183 * method returns null. 1184 * 1185 * <p>This is a convenient method mainly for obtaining 1186 * a user-defined attribute. For dealing with attributes, see the 1187 * <code>javassist.bytecode</code> package. For example, the following 1188 * expression returns all the attributes of a class file. 1189 * 1190 * <pre> 1191 * getClassFile().getAttributes() 1192 * </pre> 1193 * 1194 * @param name attribute name 1195 * @see javassist.bytecode.AttributeInfo 1196 */ getAttribute(String name)1197 public byte[] getAttribute(String name) { 1198 return null; 1199 } 1200 1201 /** 1202 * Adds a named attribute. 1203 * An arbitrary data (smaller than 64Kb) can be saved in the class 1204 * file. Some attribute name are reserved by the JVM. 1205 * The attributes with the non-reserved names are ignored when a 1206 * class file is loaded into the JVM. 1207 * If there is already an attribute with 1208 * the same name, this method substitutes the new one for it. 1209 * 1210 * <p>This is a convenient method mainly for adding 1211 * a user-defined attribute. For dealing with attributes, see the 1212 * <code>javassist.bytecode</code> package. For example, the following 1213 * expression adds an attribute <code>info</code> to a class file. 1214 * 1215 * <pre> 1216 * getClassFile().addAttribute(info) 1217 * </pre> 1218 * 1219 * @param name attribute name 1220 * @param data attribute value 1221 * @see javassist.bytecode.AttributeInfo 1222 */ setAttribute(String name, byte[] data)1223 public void setAttribute(String name, byte[] data) { 1224 checkModify(); 1225 } 1226 1227 /** 1228 * Applies the given converter to all methods and constructors 1229 * declared in the class. This method calls <code>instrument()</code> 1230 * on every <code>CtMethod</code> and <code>CtConstructor</code> object 1231 * in the class. 1232 * 1233 * @param converter specifies how to modify. 1234 */ instrument(CodeConverter converter)1235 public void instrument(CodeConverter converter) 1236 throws CannotCompileException 1237 { 1238 checkModify(); 1239 } 1240 1241 /** 1242 * Modifies the bodies of all methods and constructors 1243 * declared in the class. This method calls <code>instrument()</code> 1244 * on every <code>CtMethod</code> and <code>CtConstructor</code> object 1245 * in the class. 1246 * 1247 * @param editor specifies how to modify. 1248 */ instrument(ExprEditor editor)1249 public void instrument(ExprEditor editor) 1250 throws CannotCompileException 1251 { 1252 checkModify(); 1253 } 1254 1255 /** 1256 * Converts this class to a <code>java.lang.Class</code> object. 1257 * Once this method is called, further modifications are not 1258 * allowed any more. 1259 * To load the class, this method uses the context class loader 1260 * of the current thread. If the program is running on some application 1261 * server, the context class loader might be inappropriate to load the 1262 * class. 1263 * 1264 * <p><b>Warning:</b> In Java 11 or later, the call to this method will 1265 * print a warning message:</p> 1266 * <blockquote><pre> 1267 * WARNING: An illegal reflective access operation has occurred 1268 * WARNING: Illegal reflective access by javassist.util.proxy.SecurityActions$3 ... 1269 * WARNING: Please consider reporting this to the maintainers of javassist.util.proxy.SecurityActions$3 1270 * WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations 1271 * WARNING: All illegal access operations will be denied in a future release 1272 * </pre></blockquote> 1273 * <p>To avoid this message, use {@link #toClass(Class)} 1274 * or {@link #toClass(java.lang.invoke.MethodHandles.Lookup)}. 1275 * {@link #toClass()} will be unavailable in a future release. 1276 * </p> 1277 * 1278 * <p><b>Warning:</b> A Class object returned by this method may not 1279 * work with a security manager or a signed jar file because a 1280 * protection domain is not specified.</p> 1281 * 1282 * <p>Note: this method calls <code>toClass()</code> 1283 * in <code>ClassPool</code>.</p> 1284 * 1285 * @see #toClass(java.lang.invoke.MethodHandles.Lookup) 1286 * @see #toClass(Class) 1287 * @see ClassPool#toClass(CtClass) 1288 */ toClass()1289 public Class<?> toClass() throws CannotCompileException { 1290 return getClassPool().toClass(this); 1291 } 1292 1293 /** 1294 * Converts this class to a <code>java.lang.Class</code> object. 1295 * Once this method is called, further modifications are not 1296 * allowed any more. 1297 * 1298 * <p>This method is provided for convenience. You should use 1299 * {@code toClass(Lookup)} for better compatibility with the 1300 * module system. 1301 * 1302 * <p>Note: this method calls <code>toClass()</code> 1303 * in <code>ClassPool</code>. 1304 * 1305 * <p><b>Warning:</b> A Class object returned by this method may not 1306 * work with a security manager or a signed jar file because a 1307 * protection domain is not specified. 1308 * 1309 * @param neighbor A class belonging to the same package that this 1310 * class belongs to. It is used to load the class. 1311 * @see ClassPool#toClass(CtClass,Class) 1312 * @see #toClass(java.lang.invoke.MethodHandles.Lookup) 1313 * @since 3.24 1314 */ toClass(Class<?> neighbor)1315 public Class<?> toClass(Class<?> neighbor) throws CannotCompileException 1316 { 1317 return getClassPool().toClass(this, neighbor); 1318 } 1319 1320 /** 1321 * Converts this class to a <code>java.lang.Class</code> object. 1322 * Once this method is called, further modifications are not 1323 * allowed any more. 1324 * 1325 * <p>This method is provided for convenience. If you need more 1326 * complex functionality, you should write your own class loader. 1327 * 1328 * <p>Note: this method calls <code>toClass()</code> 1329 * in <code>ClassPool</code>. 1330 * 1331 * <p><b>Warning:</b> A Class object returned by this method may not 1332 * work with a security manager or a signed jar file because a 1333 * protection domain is not specified. 1334 * 1335 * @param lookup used when loading the class. It has to have 1336 * an access right to define a new class. 1337 * @see ClassPool#toClass(CtClass,java.lang.invoke.MethodHandles.Lookup) 1338 * @since 3.24 1339 */ toClass(java.lang.invoke.MethodHandles.Lookup lookup)1340 public Class<?> toClass(java.lang.invoke.MethodHandles.Lookup lookup) 1341 throws CannotCompileException 1342 { 1343 return getClassPool().toClass(this, lookup); 1344 } 1345 1346 /** 1347 * Converts this class to a <code>java.lang.Class</code> object. 1348 * Once this method is called, further modifications are not allowed 1349 * any more. 1350 * 1351 * <p>The class file represented by this <code>CtClass</code> is 1352 * loaded by the given class loader to construct a 1353 * <code>java.lang.Class</code> object. Since a private method 1354 * on the class loader is invoked through the reflection API, 1355 * the caller must have permissions to do that. 1356 * 1357 * <p>An easy way to obtain <code>ProtectionDomain</code> object is 1358 * to call <code>getProtectionDomain()</code> 1359 * in <code>java.lang.Class</code>. It returns the domain that 1360 * the class belongs to. 1361 * 1362 * <p>This method is provided for convenience. If you need more 1363 * complex functionality, you should write your own class loader. 1364 * 1365 * <p>Note: this method calls <code>toClass()</code> 1366 * in <code>ClassPool</code>. 1367 * 1368 * @param loader the class loader used to load this class. 1369 * If it is null, the class loader returned by 1370 * {@link ClassPool#getClassLoader()} is used. 1371 * @param domain the protection domain that the class belongs to. 1372 * If it is null, the default domain created 1373 * by <code>java.lang.ClassLoader</code> is used. 1374 * @see ClassPool#toClass(CtClass,java.lang.ClassLoader) 1375 * @since 3.3 1376 */ toClass(ClassLoader loader, ProtectionDomain domain)1377 public Class<?> toClass(ClassLoader loader, ProtectionDomain domain) 1378 throws CannotCompileException 1379 { 1380 ClassPool cp = getClassPool(); 1381 if (loader == null) 1382 loader = cp.getClassLoader(); 1383 1384 return cp.toClass(this, null, loader, domain); 1385 } 1386 1387 /** 1388 * Converts this class to a <code>java.lang.Class</code> object. 1389 * 1390 * <p><b>Warning:</b> A Class object returned by this method may not 1391 * work with a security manager or a signed jar file because a 1392 * protection domain is not specified. 1393 * 1394 * @deprecated Replaced by {@link #toClass(ClassLoader,ProtectionDomain)} 1395 */ 1396 @Deprecated toClass(ClassLoader loader)1397 public final Class<?> toClass(ClassLoader loader) 1398 throws CannotCompileException 1399 { 1400 return getClassPool().toClass(this, null, loader, null); 1401 } 1402 1403 /** 1404 * Removes this <code>CtClass</code> object from the 1405 * <code>ClassPool</code>. 1406 * After this method is called, any method cannot be called on the 1407 * removed <code>CtClass</code> object. 1408 * 1409 * <p>If <code>get()</code> in <code>ClassPool</code> is called 1410 * with the name of the removed method, 1411 * the <code>ClassPool</code> will read the class file again 1412 * and constructs another <code>CtClass</code> object representing 1413 * the same class. 1414 */ detach()1415 public void detach() { 1416 ClassPool cp = getClassPool(); 1417 CtClass obj = cp.removeCached(getName()); 1418 if (obj != this) 1419 cp.cacheCtClass(getName(), obj, false); 1420 } 1421 1422 /** 1423 * Disallows (or allows) automatically pruning this <code>CtClass</code> 1424 * object. 1425 * 1426 * <p> 1427 * Javassist can automatically prune a <code>CtClass</code> object 1428 * when <code>toBytecode()</code> (or <code>toClass()</code>, 1429 * <code>writeFile()</code>) is called. 1430 * Since a <code>ClassPool</code> holds all instances of <code>CtClass</code> 1431 * even after <code>toBytecode()</code> (or <code>toClass()</code>, 1432 * <code>writeFile()</code>) is called, pruning may significantly 1433 * save memory consumption. 1434 * 1435 * <p>If <code>ClassPool.doPruning</code> is true, the automatic pruning 1436 * is on by default. Otherwise, it is off. The default value of 1437 * <code>ClassPool.doPruning</code> is false. 1438 * 1439 * @param stop disallow pruning if true. Otherwise, allow. 1440 * @return the previous status of pruning. true if pruning is already stopped. 1441 * 1442 * @see #detach() 1443 * @see #prune() 1444 * @see ClassPool#doPruning 1445 */ stopPruning(boolean stop)1446 public boolean stopPruning(boolean stop) { return true; } 1447 1448 /** 1449 * Discards unnecessary attributes, in particular, 1450 * <code>CodeAttribute</code>s (method bodies) of the class, 1451 * to minimize the memory footprint. 1452 * After calling this method, the class is read only. 1453 * It cannot be modified any more. 1454 * Furthermore, <code>toBytecode()</code>, 1455 * <code>writeFile()</code>, <code>toClass()</code>, 1456 * or <code>instrument()</code> cannot be called. 1457 * However, the method names and signatures in the class etc. 1458 * are still accessible. 1459 * 1460 * <p><code>toBytecode()</code>, <code>writeFile()</code>, and 1461 * <code>toClass()</code> internally call this method if 1462 * automatic pruning is on. 1463 * 1464 * <p>According to some experiments, pruning does not really reduce 1465 * memory consumption. Only about 20%. Since pruning takes time, 1466 * it might not pay off. So the automatic pruning is off by default. 1467 * 1468 * @see #stopPruning(boolean) 1469 * @see #detach() 1470 * @see ClassPool#doPruning 1471 * 1472 * @see #toBytecode() 1473 * @see #toClass(Class) 1474 * @see #writeFile() 1475 * @see #instrument(CodeConverter) 1476 * @see #instrument(ExprEditor) 1477 */ prune()1478 public void prune() {} 1479 1480 /* Called by get() in ClassPool. 1481 * CtClassType overrides this method. 1482 */ incGetCounter()1483 void incGetCounter() {} 1484 1485 /** 1486 * If this method is called, the class file will be 1487 * rebuilt when it is finally generated by 1488 * <code>toBytecode()</code> and <code>writeFile()</code>. 1489 * For a performance reason, the symbol table of the 1490 * class file may contain unused entries, for example, 1491 * after a method or a filed is deleted. 1492 * This method 1493 * removes those unused entries. This removal will 1494 * minimize the size of the class file. 1495 * 1496 * @since 3.8.1 1497 */ rebuildClassFile()1498 public void rebuildClassFile() {} 1499 1500 /** 1501 * Converts this class to a class file. 1502 * Once this method is called, further modifications are not 1503 * possible any more. 1504 * 1505 * @return the contents of the class file. 1506 */ toBytecode()1507 public byte[] toBytecode() throws IOException, CannotCompileException { 1508 ByteArrayOutputStream barray = new ByteArrayOutputStream(); 1509 DataOutputStream out = new DataOutputStream(barray); 1510 try { 1511 toBytecode(out); 1512 } 1513 finally { 1514 out.close(); 1515 } 1516 1517 return barray.toByteArray(); 1518 } 1519 1520 /** 1521 * Writes a class file represented by this <code>CtClass</code> 1522 * object in the current directory. 1523 * Once this method is called, further modifications are not 1524 * possible any more. 1525 * 1526 * @see #debugWriteFile() 1527 */ writeFile()1528 public void writeFile() 1529 throws NotFoundException, IOException, CannotCompileException 1530 { 1531 writeFile("."); 1532 } 1533 1534 /** 1535 * Writes a class file represented by this <code>CtClass</code> 1536 * object on a local disk. 1537 * Once this method is called, further modifications are not 1538 * possible any more. 1539 * 1540 * @param directoryName it must end without a directory separator. 1541 * @see #debugWriteFile(String) 1542 */ writeFile(String directoryName)1543 public void writeFile(String directoryName) 1544 throws CannotCompileException, IOException 1545 { 1546 DataOutputStream out = makeFileOutput(directoryName); 1547 try { 1548 toBytecode(out); 1549 } 1550 finally { 1551 out.close(); 1552 } 1553 } 1554 makeFileOutput(String directoryName)1555 protected DataOutputStream makeFileOutput(String directoryName) { 1556 String classname = getName(); 1557 String filename = directoryName + File.separatorChar 1558 + classname.replace('.', File.separatorChar) + ".class"; 1559 int pos = filename.lastIndexOf(File.separatorChar); 1560 if (pos > 0) { 1561 String dir = filename.substring(0, pos); 1562 if (!dir.equals(".")) 1563 new File(dir).mkdirs(); 1564 } 1565 1566 return new DataOutputStream(new BufferedOutputStream( 1567 new DelayedFileOutputStream(filename))); 1568 } 1569 1570 /** 1571 * Writes a class file as <code>writeFile()</code> does although this 1572 * method does not prune or freeze the class after writing the class 1573 * file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code> 1574 * is called, it cannot be called again since the class is pruned and frozen. 1575 * This method would be useful for debugging. 1576 */ debugWriteFile()1577 public void debugWriteFile() { 1578 debugWriteFile("."); 1579 } 1580 1581 /** 1582 * Writes a class file as <code>writeFile()</code> does although this 1583 * method does not prune or freeze the class after writing the class 1584 * file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code> 1585 * is called, it cannot be called again since the class is pruned and frozen. 1586 * This method would be useful for debugging. 1587 * 1588 * @param directoryName it must end without a directory separator. 1589 */ debugWriteFile(String directoryName)1590 public void debugWriteFile(String directoryName) { 1591 try { 1592 boolean p = stopPruning(true); 1593 writeFile(directoryName); 1594 defrost(); 1595 stopPruning(p); 1596 } 1597 catch (Exception e) { 1598 throw new RuntimeException(e); 1599 } 1600 } 1601 1602 static class DelayedFileOutputStream extends OutputStream { 1603 private FileOutputStream file; 1604 private String filename; 1605 DelayedFileOutputStream(String name)1606 DelayedFileOutputStream(String name) { 1607 file = null; 1608 filename = name; 1609 } 1610 init()1611 private void init() throws IOException { 1612 if (file == null) 1613 file = new FileOutputStream(filename); 1614 } 1615 1616 @Override write(int b)1617 public void write(int b) throws IOException { 1618 init(); 1619 file.write(b); 1620 } 1621 1622 @Override write(byte[] b)1623 public void write(byte[] b) throws IOException { 1624 init(); 1625 file.write(b); 1626 } 1627 1628 @Override write(byte[] b, int off, int len)1629 public void write(byte[] b, int off, int len) throws IOException { 1630 init(); 1631 file.write(b, off, len); 1632 1633 } 1634 1635 @Override flush()1636 public void flush() throws IOException { 1637 init(); 1638 file.flush(); 1639 } 1640 1641 @Override close()1642 public void close() throws IOException { 1643 init(); 1644 file.close(); 1645 } 1646 } 1647 1648 /** 1649 * Converts this class to a class file. 1650 * Once this method is called, further modifications are not 1651 * possible any more. 1652 * 1653 * <p>This method dose not close the output stream in the end. 1654 * 1655 * @param out the output stream that a class file is written to. 1656 */ toBytecode(DataOutputStream out)1657 public void toBytecode(DataOutputStream out) 1658 throws CannotCompileException, IOException 1659 { 1660 throw new CannotCompileException("not a class"); 1661 } 1662 1663 /** 1664 * Makes a unique member name. This method guarantees that 1665 * the returned name is not used as a prefix of any methods 1666 * or fields visible in this class. 1667 * If the returned name is XYZ, then any method or field names 1668 * in this class do not start with XYZ. 1669 * 1670 * @param prefix the prefix of the member name. 1671 */ makeUniqueName(String prefix)1672 public String makeUniqueName(String prefix) { 1673 throw new RuntimeException("not available in " + getName()); 1674 } 1675 1676 /* Invoked from ClassPool#compress(). 1677 * This method is overridden by CtClassType. 1678 */ compress()1679 void compress() {} 1680 } 1681