com.feilong.lib.javassist.CtClass Maven / Gradle / Ivy
Show all versions of feilong Show documentation
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.feilong.lib.javassist;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.Collection;
import com.feilong.lib.javassist.bytecode.ClassFile;
import com.feilong.lib.javassist.bytecode.Descriptor;
import com.feilong.lib.javassist.bytecode.Opcode;
import com.feilong.lib.javassist.expr.ExprEditor;
/* Note:
*
* This class is an abstract class and several methods just return null
* or throw an exception. Those methods are overridden in subclasses
* of this class. Read the source code of CtClassType if you are
* interested in the implementation of Javassist.
*
* Subclasses of CtClass are CtClassType, CtPrimitiveType, and CtArray.
*/
/**
* An instance of CtClass
represents a class.
* It is obtained from ClassPool
.
*
* @see ClassPool#get(String)
*/
public abstract class CtClass{
protected String qualifiedName;
/**
* If the value of this field is not null, then all class
* files modified by Javassist are saved under the directory
* specified by this variable. For example, if the value is
* "./debug"
, then all class files are saved
* there. The directory name must not end with a directory
* separator such as /
.
*
*
* The default value is null.
*
* @see #debugWriteFile(String)
* @since 3.16
*/
public static String debugDump = null;
/**
* The version number of this release.
*/
public static final String version = "3.24.1-GA";
static final String javaLangObject = "java.lang.Object";
/**
* The CtClass
object representing
* the boolean
type.
*/
public static CtClass booleanType;
/**
* The CtClass
object representing
* the char
type.
*/
public static CtClass charType;
/**
* The CtClass
object representing
* the byte
type.
*/
public static CtClass byteType;
/**
* The CtClass
object representing
* the short
type.
*/
public static CtClass shortType;
/**
* The CtClass
object representing
* the int
type.
*/
public static CtClass intType;
/**
* The CtClass
object representing
* the long
type.
*/
public static CtClass longType;
/**
* The CtClass
object representing
* the float
type.
*/
public static CtClass floatType;
/**
* The CtClass
object representing
* the double
type.
*/
public static CtClass doubleType;
/**
* The CtClass
object representing
* the void
type.
*/
public static CtClass voidType;
static CtClass[] primitiveTypes;
static{
primitiveTypes = new CtClass[9];
booleanType = new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean", "booleanValue", "()Z", Opcode.IRETURN, Opcode.T_BOOLEAN, 1);
primitiveTypes[0] = booleanType;
charType = new CtPrimitiveType("char", 'C', "java.lang.Character", "charValue", "()C", Opcode.IRETURN, Opcode.T_CHAR, 1);
primitiveTypes[1] = charType;
byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte", "byteValue", "()B", Opcode.IRETURN, Opcode.T_BYTE, 1);
primitiveTypes[2] = byteType;
shortType = new CtPrimitiveType("short", 'S', "java.lang.Short", "shortValue", "()S", Opcode.IRETURN, Opcode.T_SHORT, 1);
primitiveTypes[3] = shortType;
intType = new CtPrimitiveType("int", 'I', "java.lang.Integer", "intValue", "()I", Opcode.IRETURN, Opcode.T_INT, 1);
primitiveTypes[4] = intType;
longType = new CtPrimitiveType("long", 'J', "java.lang.Long", "longValue", "()J", Opcode.LRETURN, Opcode.T_LONG, 2);
primitiveTypes[5] = longType;
floatType = new CtPrimitiveType("float", 'F', "java.lang.Float", "floatValue", "()F", Opcode.FRETURN, Opcode.T_FLOAT, 1);
primitiveTypes[6] = floatType;
doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double", "doubleValue", "()D", Opcode.DRETURN, Opcode.T_DOUBLE, 2);
primitiveTypes[7] = doubleType;
voidType = new CtPrimitiveType("void", 'V', "java.lang.Void", null, null, Opcode.RETURN, 0, 0);
primitiveTypes[8] = voidType;
}
protected CtClass(String name){
qualifiedName = name;
}
/**
* Converts the object to a string.
*/
@Override
public String toString(){
StringBuffer buf = new StringBuffer(getClass().getName());
buf.append("@");
buf.append(Integer.toHexString(hashCode()));
buf.append("[");
extendToString(buf);
buf.append("]");
return buf.toString();
}
/**
* Implemented in subclasses to add to the {@link #toString()} result.
* Subclasses should put a space before each token added to the buffer.
*/
protected void extendToString(StringBuffer buffer){
buffer.append(getName());
}
/**
* Returns a ClassPool
for this class.
*/
public ClassPool getClassPool(){
return null;
}
/**
* Returns a class file for this class.
*
*
* This method is not available if isFrozen()
* is true.
*/
public ClassFile getClassFile(){
checkModify();
return getClassFile2();
}
/**
* Returns a class file for this class (read only).
* Normal applications do not need calling this method. Use
* getClassFile()
.
*
*
* The ClassFile
object obtained by this method
* is read only. Changes to this object might not be reflected
* on a class file generated by toBytecode()
,
* toClass()
, etc.
*
*
* This method is available even if isFrozen()
* is true. However, if the class is frozen, it might be also
* pruned.
*
* @see CtClass#getClassFile()
* @see CtClass#isFrozen()
* @see CtClass#prune()
*/
public ClassFile getClassFile2(){
return null;
}
/**
* Undocumented method. Do not use; internal-use only.
*/
public com.feilong.lib.javassist.compiler.AccessorMaker getAccessorMaker(){
return null;
}
/**
* Returns the uniform resource locator (URL) of the class file.
*/
public URL getURL() throws NotFoundException{
throw new NotFoundException(getName());
}
/**
* Returns true if the definition of the class has been modified.
*/
public boolean isModified(){
return false;
}
/**
* Returns true if the class has been loaded or written out
* and thus it cannot be modified any more.
*
* @see #defrost()
* @see #detach()
*/
public boolean isFrozen(){
return true;
}
/**
* Makes the class frozen.
*
* @see #isFrozen()
* @see #defrost()
* @since 3.6
*/
public void freeze(){
}
/*
* Note: this method is overridden by CtClassType
*/
void checkModify() throws RuntimeException{
if (isFrozen()){
throw new RuntimeException(getName() + " class is frozen");
}
// isModified() must return true after this method is invoked.
}
/**
* Defrosts the class so that the class can be modified again.
*
*
* To avoid changes that will be never reflected,
* the class is frozen to be unmodifiable if it is loaded or
* written out. This method should be called only in a case
* that the class will be reloaded or written out later again.
*
*
* If defrost()
will be called later, pruning
* must be disallowed in advance.
*
* @see #isFrozen()
* @see #stopPruning(boolean)
* @see #detach()
*/
public void defrost(){
throw new RuntimeException("cannot defrost " + getName());
}
/**
* Returns true
if this object represents a primitive
* Java type: boolean, byte, char, short, int, long, float, double,
* or void.
*/
public boolean isPrimitive(){
return false;
}
/**
* Returns true
if this object represents an array type.
*/
public boolean isArray(){
return false;
}
/**
* If this object represents an array, this method returns the component
* type of the array. Otherwise, it returns null
.
*/
public CtClass getComponentType() throws NotFoundException{
return null;
}
/**
* Returns true
if this class extends or implements
* clazz
. It also returns true
if
* this class is the same as clazz
.
*/
public boolean subtypeOf(CtClass clazz) throws NotFoundException{
return this == clazz || getName().equals(clazz.getName());
}
/**
* Obtains the fully-qualified name of the class.
*/
public String getName(){
return qualifiedName;
}
/**
* Obtains the not-qualified class name.
*/
public final String getSimpleName(){
String qname = qualifiedName;
int index = qname.lastIndexOf('.');
if (index < 0){
return qname;
}
return qname.substring(index + 1);
}
/**
* Obtains the package name. It may be null
.
*/
public final String getPackageName(){
String qname = qualifiedName;
int index = qname.lastIndexOf('.');
if (index < 0){
return null;
}
return qname.substring(0, index);
}
/**
* Sets the class name
*
* @param name
* fully-qualified name
*/
public void setName(String name){
checkModify();
if (name != null){
qualifiedName = name;
}
}
/**
* Returns the generic signature of the class.
*
*
* The generics of Java is implemented by the erasure technique.
* After compilation, all type parameters are dropped off from the
* main part of a class file. However, for reflection, the type
* parameters are encoded into generic signatures and attached
* to a class file.
*
* @return null if the generic signature is not included.
* @see com.feilong.lib.javassist.bytecode.SignatureAttribute#toClassSignature(String)
* @see CtMember#getGenericSignature()
* @since 3.17
*/
public String getGenericSignature(){
return null;
}
/**
* Sets the generic signature of the class.
*
*
* The generics of Java is implemented by the erasure technique.
* After compilation, all type parameters are dropped off from the
* main part of a class file. However, for reflection, the type
* parameters must be encoded into generic signatures and attached
* to a class file.
*
*
* For example,
*
*
* class List<T> {
*
* T value;
*
* T get(){
* return value;
* }
*
* void set(T v){
* value = v;
* }
* }
*
*
*
* this class is generated by the following code:
*
*
* ClassPool pool = ClassPool.getDefault();
* CtClass cc = pool.makeClass("List");
* CtClass objectClass = pool.get(CtClass.javaLangObject);
* ClassSignature cs = new ClassSignature(new TypeParameter[] { new TypeParameter("T") });
* cc.setGenericSignature(cs.encode()); // <T:Ljava/lang/Object;>Ljava/lang/Object;
*
* CtField f = new CtField(objClass, "value", cc);
* TypeVariable tvar = new TypeVariable("T");
* f.setGenericSignature(tvar.encode()); // TT;
* cc.addField(f);
*
* CtMethod m = CtNewMethod.make("public Object get(){return value;}", cc);
* MethodSignature ms = new MethodSignature(null, null, tvar, null);
* m.setGenericSignature(ms.encode()); // ()TT;
* cc.addMethod(m);
*
* CtMethod m2 = CtNewMethod.make("public void set(Object v){value = v;}", cc);
* MethodSignature ms2 = new MethodSignature(null, new Type[] { tvar }, new BaseType("void"), null);
* m2.setGenericSignature(ms2.encode()); // (TT;)V;
* cc.addMethod(m2);
*
* cc.writeFile();
*
*
*
* The generated class file is equivalent to the following:
*
*
* class List{
*
* Object value;
*
* Object get(){
* return value;
* }
*
* void set(Object v){
* value = v;
* }
* }
*
*
*
* but it includes generic signatures for the class, the field,
* and the methods so that the type variable T
can be
* accessible through reflection.
*
*
* MethodSignature
is a utility class. You can directly
* pass the signature string to the setGenericSignature
method.
* For the specification of the signatures, see Section 4.7.9.1 Signatures
* of The Java Virtual Machine Specification (Java SE 8).
*
* @param sig
* a generic signature.
* @see com.feilong.lib.javassist.bytecode.SignatureAttribute.ClassSignature#encode()
* @see com.feilong.lib.javassist.bytecode.SignatureAttribute.MethodSignature#encode()
* @see CtMember#setGenericSignature(String)
* @since 3.17
*/
public void setGenericSignature(String sig){
checkModify();
}
/**
* Substitutes newName
for all occurrences of a class
* name oldName
in the class file.
*
* @param oldName
* replaced class name
* @param newName
* substituted class name
*/
public void replaceClassName(String oldName,String newName){
checkModify();
}
/**
* Changes class names appearing in the class file according to the
* given map
.
*
*
* All the class names appearing in the class file are tested
* with map
to determine whether each class name is
* replaced or not. Thus this method can be used for collecting
* all the class names in the class file. To do that, first define
* a subclass of ClassMap
so that get()
* records all the given parameters. Then, make an instance of
* that subclass as an empty hash-table. Finally, pass that instance
* to this method. After this method finishes, that instance would
* contain all the class names appearing in the class file.
*
* @param map
* the hashtable associating replaced class names
* with substituted names.
*/
public void replaceClassName(ClassMap map){
checkModify();
}
/**
* Returns a collection of the names of all the classes
* referenced in this class.
* That collection includes the name of this class.
*
*
* This method may return null
.
*
* @return a Collection<String>
object.
*/
public synchronized Collection getRefClasses(){
ClassFile cf = getClassFile2();
if (cf != null){
ClassMap cm = new ClassMap(){
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
@Override
public String put(String oldname,String newname){
return put0(oldname, newname);
}
@Override
public String get(Object jvmClassName){
String n = toJavaName((String) jvmClassName);
put0(n, n);
return null;
}
@Override
public void fix(String name){
}
};
cf.getRefClasses(cm);
return cm.values();
}
return null;
}
/**
* Determines whether this object represents a class or an interface.
* It returns true
if this object represents an interface.
*/
public boolean isInterface(){
return false;
}
/**
* Determines whether this object represents an annotation type.
* It returns true
if this object represents an annotation type.
*
* @since 3.2
*/
public boolean isAnnotation(){
return false;
}
/**
* Determines whether this object represents an enum.
* It returns true
if this object represents an enum.
*
* @since 3.2
*/
public boolean isEnum(){
return false;
}
/**
* Returns the modifiers for this class, encoded in an integer.
* For decoding, use javassist.Modifier
.
*
*
* If the class is a static nested class (a.k.a. static inner class),
* the returned modifiers include Modifier.STATIC
.
*
* @see Modifier
*/
public int getModifiers(){
return 0;
}
/**
* Returns true if the class has the specified annotation type.
*
* @param annotationType
* the annotation type.
* @return true
if the annotation is found, otherwise false
.
* @since 3.11
*/
public boolean hasAnnotation(Class annotationType){
return hasAnnotation(annotationType.getName());
}
/**
* Returns true if the class has the specified annotation type.
*
* @param annotationTypeName
* the name of annotation type.
* @return true
if the annotation is found, otherwise false
.
* @since 3.21
*/
public boolean hasAnnotation(String annotationTypeName){
return false;
}
/**
* Returns the annotation if the class has the specified annotation type.
* For example, if an annotation @Author
is associated
* with this class, an Author
object is returned.
* The member values can be obtained by calling methods on
* the Author
object.
*
* @param clz
* the annotation type.
* @return the annotation if found, otherwise null
.
* @since 3.11
*/
public Object getAnnotation(Class clz) throws ClassNotFoundException{
return null;
}
/**
* Returns the annotations associated with this class.
* For example, if an annotation @Author
is associated
* with this class, the returned array contains an Author
* object. The member values can be obtained by calling methods on
* the Author
object.
*
* @return an array of annotation-type objects.
* @see CtMember#getAnnotations()
* @since 3.1
*/
public Object[] getAnnotations() throws ClassNotFoundException{
return new Object[0];
}
/**
* Returns the annotations associated with this class.
* This method is equivalent to getAnnotations()
* except that, if any annotations are not on the classpath,
* they are not included in the returned array.
*
* @return an array of annotation-type objects.
* @see #getAnnotations()
* @see CtMember#getAvailableAnnotations()
* @since 3.3
*/
public Object[] getAvailableAnnotations(){
return new Object[0];
}
/**
* Returns an array of nested classes declared in the class.
* Nested classes are inner classes, anonymous classes, local classes,
* and static nested classes. This simply calls getNestedClasses()
.
*
* @see #getNestedClasses()
* @since 3.15
*/
public CtClass[] getDeclaredClasses() throws NotFoundException{
return getNestedClasses();
}
/**
* Returns an array of nested classes declared in the class.
* Nested classes are inner classes, anonymous classes, local classes,
* and static nested classes.
*
* @since 3.2
*/
public CtClass[] getNestedClasses() throws NotFoundException{
return new CtClass[0];
}
/**
* Sets the modifiers.
*
*
* If the class is a nested class, this method also modifies
* the class declaring that nested class (i.e. the enclosing
* class is modified).
*
* @param mod
* modifiers encoded by
* javassist.Modifier
* @see Modifier
*/
public void setModifiers(int mod){
checkModify();
}
/**
* Determines whether the class directly or indirectly extends
* the given class. If this class extends a class A and
* the class A extends a class B, then subclassof(B) returns true.
*
*
* This method returns true if the given class is identical to
* the class represented by this object.
*/
public boolean subclassOf(CtClass superclass){
return false;
}
/**
* Obtains the class object representing the superclass of the
* class.
* It returns null if this object represents the
* java.lang.Object
class and thus it does not have
* the super class.
*
*
* If this object represents an interface, this method
* always returns the java.lang.Object
class.
* To obtain the super interfaces
* extended by that interface, call getInterfaces()
.
*/
public CtClass getSuperclass() throws NotFoundException{
return null;
}
/**
* Changes a super class unless this object represents an interface.
* The new super class must be compatible with the old one; for example,
* it should inherit from the old super class.
*
*
* If this object represents an interface, this method is equivalent
* to addInterface()
; it appends clazz
to
* the list of the super interfaces extended by that interface.
* Note that an interface can extend multiple super interfaces.
*
* @see #replaceClassName(String, String)
* @see #replaceClassName(ClassMap)
*/
public void setSuperclass(CtClass clazz) throws CannotCompileException{
checkModify();
}
/**
* Obtains the class objects representing the interfaces implemented
* by the class or, if this object represents an interface, the interfaces
* extended by that interface.
*/
public CtClass[] getInterfaces() throws NotFoundException{
return new CtClass[0];
}
/**
* Sets implemented interfaces. If this object represents an interface,
* this method sets the interfaces extended by that interface.
*
* @param list
* a list of the CtClass
objects
* representing interfaces, or
* null
if the class implements
* no interfaces.
*/
public void setInterfaces(CtClass[] list){
checkModify();
}
/**
* Adds an interface.
*
* @param anInterface
* the added interface.
*/
public void addInterface(CtClass anInterface){
checkModify();
}
/**
* If this class is a member class or interface of another class,
* then the class enclosing this class is returned.
*
* @return null if this class is a top-level class or an anonymous class.
*/
public CtClass getDeclaringClass() throws NotFoundException{
return null;
}
/**
* Returns the immediately enclosing method of this class.
* This method works only with JDK 1.5 or later.
*
* @return null if this class is not a local class or an anonymous
* class.
* @deprecated The enclosing method might be a constructor.
* Use {@link #getEnclosingBehavior()}.
* @see #getEnclosingBehavior()
*/
@Deprecated
public final CtMethod getEnclosingMethod() throws NotFoundException{
CtBehavior b = getEnclosingBehavior();
if (b == null){
return null;
}else if (b instanceof CtMethod){
return (CtMethod) b;
}else{
throw new NotFoundException(b.getLongName() + " is enclosing " + getName());
}
}
/**
* Returns the immediately enclosing method of this class.
* It might be not a method but a constructor.
* This method works only with JDK 1.5 or later.
*
* @return null if this class is not a local class or an anonymous
* class.
*/
public CtBehavior getEnclosingBehavior() throws NotFoundException{
return null;
}
/**
* Makes a new public nested class. If this method is called,
* the CtClass
, which encloses the nested class, is modified
* since a class file includes a list of nested classes.
*
*
* The current implementation only supports a static nested class.
* isStatic
must be true.
*
* @param name
* the simple name of the nested class.
* @param isStatic
* true if the nested class is static.
*/
public CtClass makeNestedClass(String name,boolean isStatic){
throw new RuntimeException(getName() + " is not a class");
}
/**
* Returns an array containing CtField
objects
* representing all the non-private fields of the class.
* That array includes non-private fields inherited from the
* superclasses.
*/
public CtField[] getFields(){
return new CtField[0];
}
/**
* Returns the field with the specified name. The returned field
* may be a private field declared in a super class or interface.
*/
public CtField getField(String name) throws NotFoundException{
return getField(name, null);
}
/**
* Returns the field with the specified name and type. The returned field
* may be a private field declared in a super class or interface.
* Unlike Java, the JVM allows a class to have
* multiple fields with the same name but different types.
*
* @param name
* the field name.
* @param desc
* the type descriptor of the field. It is available by
* {@link CtField#getSignature()}.
* @see CtField#getSignature()
*/
public CtField getField(String name,String desc) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* @return null if the specified field is not found.
*/
CtField getField2(String name,String desc){
return null;
}
/**
* Gets all the fields declared in the class. The inherited fields
* are not included.
*
*
* Note: the result does not include inherited fields.
*/
public CtField[] getDeclaredFields(){
return new CtField[0];
}
/**
* Retrieves the field with the specified name among the fields
* declared in the class.
*
*
* Note: this method does not search the super classes.
*/
public CtField getDeclaredField(String name) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* Retrieves the field with the specified name and type among the fields
* declared in the class. Unlike Java, the JVM allows a class to have
* multiple fields with the same name but different types.
*
*
* Note: this method does not search the super classes.
*
* @param name
* the field name.
* @param desc
* the type descriptor of the field. It is available by
* {@link CtField#getSignature()}.
* @see CtField#getSignature()
*/
public CtField getDeclaredField(String name,String desc) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* Gets all the constructors and methods declared in the class.
*/
public CtBehavior[] getDeclaredBehaviors(){
return new CtBehavior[0];
}
/**
* Returns an array containing CtConstructor
objects
* representing all the non-private constructors of the class.
*/
public CtConstructor[] getConstructors(){
return new CtConstructor[0];
}
/**
* Returns the constructor with the given signature,
* which is represented by a character string
* called method descriptor.
* For details of the method descriptor, see the JVM specification
* or javassist.bytecode.Descriptor
.
*
* @param desc
* method descriptor
* @see com.feilong.lib.javassist.bytecode.Descriptor
*/
public CtConstructor getConstructor(String desc) throws NotFoundException{
throw new NotFoundException("no such constructor");
}
/**
* Gets all the constructors declared in the class.
*
* @see com.feilong.lib.javassist.CtConstructor
*/
public CtConstructor[] getDeclaredConstructors(){
return new CtConstructor[0];
}
/**
* Returns a constructor receiving the specified parameters.
*
* @param params
* parameter types.
*/
public CtConstructor getDeclaredConstructor(CtClass[] params) throws NotFoundException{
String desc = Descriptor.ofConstructor(params);
return getConstructor(desc);
}
/**
* Gets the class initializer (static constructor)
* declared in the class.
* This method returns null
if
* no class initializer is not declared.
*
* @see #makeClassInitializer()
* @see com.feilong.lib.javassist.CtConstructor
*/
public CtConstructor getClassInitializer(){
return null;
}
/**
* Returns an array containing CtMethod
objects
* representing all the non-private methods of the class.
* That array includes non-private methods inherited from the
* superclasses.
*/
public CtMethod[] getMethods(){
return new CtMethod[0];
}
/**
* Returns the method with the given name and signature.
* The returned method may be declared in a super class.
* The method signature is represented by a character string
* called method descriptor,
* which is defined in the JVM specification.
*
* @param name
* method name
* @param desc
* method descriptor
* @see CtBehavior#getSignature()
* @see com.feilong.lib.javassist.bytecode.Descriptor
*/
public CtMethod getMethod(String name,String desc) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* Gets all methods declared in the class. The inherited methods
* are not included.
*
* @see com.feilong.lib.javassist.CtMethod
*/
public CtMethod[] getDeclaredMethods(){
return new CtMethod[0];
}
/**
* Retrieves the method with the specified name and parameter types
* among the methods declared in the class.
*
*
* Note: this method does not search the superclasses.
*
* @param name
* method name
* @param params
* parameter types
* @see com.feilong.lib.javassist.CtMethod
*/
public CtMethod getDeclaredMethod(String name,CtClass[] params) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* Retrieves methods with the specified name among the methods
* declared in the class. Multiple methods with different parameters
* may be returned.
*
*
* Note: this method does not search the superclasses.
*
*
* @param name
* method name.
* @since 3.19
*/
public CtMethod[] getDeclaredMethods(String name) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* Retrieves the method with the specified name among the methods
* declared in the class. If there are multiple methods with
* the specified name, then this method returns one of them.
*
*
* Note: this method does not search the superclasses.
*
* @see com.feilong.lib.javassist.CtMethod
*/
public CtMethod getDeclaredMethod(String name) throws NotFoundException{
throw new NotFoundException(name);
}
/**
* Makes an empty class initializer (static constructor).
* If the class already includes a class initializer,
* this method returns it.
*
* @see #getClassInitializer()
*/
public CtConstructor makeClassInitializer() throws CannotCompileException{
throw new CannotCompileException("not a class");
}
/**
* Adds a constructor. To add a class initializer (static constructor),
* call makeClassInitializer()
.
*
* @see #makeClassInitializer()
*/
public void addConstructor(CtConstructor c) throws CannotCompileException{
checkModify();
}
/**
* Removes a constructor declared in this class.
*
* @param c
* removed constructor.
* @throws NotFoundException
* if the constructor is not found.
*/
public void removeConstructor(CtConstructor c) throws NotFoundException{
checkModify();
}
/**
* Adds a method.
*/
public void addMethod(CtMethod m) throws CannotCompileException{
checkModify();
}
/**
* Removes a method declared in this class.
*
* @param m
* removed method.
* @throws NotFoundException
* if the method is not found.
*/
public void removeMethod(CtMethod m) throws NotFoundException{
checkModify();
}
/**
* Adds a field.
*
*
* The CtField
belonging to another
* CtClass
cannot be directly added to this class.
* Only a field created for this class can be added.
*
* @see com.feilong.lib.javassist.CtField#CtField(CtField,CtClass)
*/
public void addField(CtField f) throws CannotCompileException{
addField(f, (CtField.Initializer) null);
}
/**
* Adds a field with an initial value.
*
*
* The CtField
belonging to another
* CtClass
cannot be directly added to this class.
* Only a field created for this class can be added.
*
*
* The initial value is given as an expression written in Java.
* Any regular Java expression can be used for specifying the initial
* value. The followings are examples.
*
*
* cc.addField(f, "0") // the initial value is 0.
* cc.addField(f, "i + 1") // i + 1.
* cc.addField(f, "new Point()"); // a Point object.
*
*
*
* Here, the type of variable cc
is CtClass
.
* The type of f
is CtField
.
*
*
* Note: do not change the modifier of the field
* (in particular, do not add or remove static
* to/from the modifier)
* after it is added to the class by addField()
.
*
* @param init
* an expression for the initial value.
*
* @see com.feilong.lib.javassist.CtField.Initializer#byExpr(String)
* @see com.feilong.lib.javassist.CtField#CtField(CtField,CtClass)
*/
public void addField(CtField f,String init) throws CannotCompileException{
checkModify();
}
/**
* Adds a field with an initial value.
*
*
* The CtField
belonging to another
* CtClass
cannot be directly added to this class.
* Only a field created for this class can be added.
*
*
* For example,
*
*
* CtClass cc = ...;
* addField(new CtField(CtClass.intType, "i", cc),
* CtField.Initializer.constant(1));
*
*
*
* This code adds an int
field named "i". The
* initial value of this field is 1.
*
* @param init
* specifies the initial value of the field.
*
* @see com.feilong.lib.javassist.CtField#CtField(CtField,CtClass)
*/
public void addField(CtField f,CtField.Initializer init) throws CannotCompileException{
checkModify();
}
/**
* Removes a field declared in this class.
*
* @param f
* removed field.
* @throws NotFoundException
* if the field is not found.
*/
public void removeField(CtField f) throws NotFoundException{
checkModify();
}
/**
* Obtains an attribute with the given name.
* If that attribute is not found in the class file, this
* method returns null.
*
*
* This is a convenient method mainly for obtaining
* a user-defined attribute. For dealing with attributes, see the
* javassist.bytecode
package. For example, the following
* expression returns all the attributes of a class file.
*
*
* getClassFile().getAttributes()
*
*
* @param name
* attribute name
* @see com.feilong.lib.javassist.bytecode.AttributeInfo
*/
public byte[] getAttribute(String name){
return null;
}
/**
* Adds a named attribute.
* An arbitrary data (smaller than 64Kb) can be saved in the class
* file. Some attribute name are reserved by the JVM.
* The attributes with the non-reserved names are ignored when a
* class file is loaded into the JVM.
* If there is already an attribute with
* the same name, this method substitutes the new one for it.
*
*
* This is a convenient method mainly for adding
* a user-defined attribute. For dealing with attributes, see the
* javassist.bytecode
package. For example, the following
* expression adds an attribute info
to a class file.
*
*
* getClassFile().addAttribute(info)
*
*
* @param name
* attribute name
* @param data
* attribute value
* @see com.feilong.lib.javassist.bytecode.AttributeInfo
*/
public void setAttribute(String name,byte[] data){
checkModify();
}
/**
* Applies the given converter to all methods and constructors
* declared in the class. This method calls instrument()
* on every CtMethod
and CtConstructor
object
* in the class.
*
* @param converter
* specifies how to modify.
*/
public void instrument(CodeConverter converter) throws CannotCompileException{
checkModify();
}
/**
* Modifies the bodies of all methods and constructors
* declared in the class. This method calls instrument()
* on every CtMethod
and CtConstructor
object
* in the class.
*
* @param editor
* specifies how to modify.
*/
public void instrument(ExprEditor editor) throws CannotCompileException{
checkModify();
}
/**
* Converts this class to a java.lang.Class
object.
* Once this method is called, further modifications are not
* allowed any more.
* To load the class, this method uses the context class loader
* of the current thread. If the program is running on some application
* server, the context class loader might be inappropriate to load the
* class.
*
*
* Warning: In Java 11 or later, the call to this method will
* print a warning message:
*
*
*
*
* WARNING: An illegal reflective access operation has occurred
* WARNING: Illegal reflective access by javassist.util.proxy.SecurityActions$3 ...
* WARNING: Please consider reporting this to the maintainers of javassist.util.proxy.SecurityActions$3
* WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
* WARNING: All illegal access operations will be denied in a future release
*
*
*
*
* To avoid this message, use {@link #toClass(Class)}
* or {@link #toClass(java.lang.invoke.MethodHandles.Lookup)}.
* {@link #toClass()} will be unavailable in a future release.
*
*
*
* Warning: A Class object returned by this method may not
* work with a security manager or a signed jar file because a
* protection domain is not specified.
*
*
*
* Note: this method calls toClass()
* in ClassPool
.
*
*
* @see #toClass(java.lang.invoke.MethodHandles.Lookup)
* @see #toClass(Class)
* @see ClassPool#toClass(CtClass)
*/
public Class toClass() throws CannotCompileException{
return getClassPool().toClass(this);
}
/**
* Converts this class to a java.lang.Class
object.
* Once this method is called, further modifications are not allowed
* any more.
*
*
* The class file represented by this CtClass
is
* loaded by the given class loader to construct a
* java.lang.Class
object. Since a private method
* on the class loader is invoked through the reflection API,
* the caller must have permissions to do that.
*
*
* An easy way to obtain ProtectionDomain
object is
* to call getProtectionDomain()
* in java.lang.Class
. It returns the domain that
* the class belongs to.
*
*
* This method is provided for convenience. If you need more
* complex functionality, you should write your own class loader.
*
*
* Note: this method calls toClass()
* in ClassPool
.
*
* @param loader
* the class loader used to load this class.
* If it is null, the class loader returned by
* {@link ClassPool#getClassLoader()} is used.
* @param domain
* the protection domain that the class belongs to.
* If it is null, the default domain created
* by java.lang.ClassLoader
is used.
* @see ClassPool#toClass(CtClass,java.lang.ClassLoader)
* @since 3.3
*/
public Class toClass(ClassLoader loader,ProtectionDomain domain) throws CannotCompileException{
ClassPool cp = getClassPool();
if (loader == null){
loader = cp.getClassLoader();
}
return cp.toClass(this, null, loader, domain);
}
/**
* Converts this class to a java.lang.Class
object.
*
*
* Warning: A Class object returned by this method may not
* work with a security manager or a signed jar file because a
* protection domain is not specified.
*
* @deprecated Replaced by {@link #toClass(ClassLoader,ProtectionDomain)}
*/
@Deprecated
public final Class toClass(ClassLoader loader) throws CannotCompileException{
return getClassPool().toClass(this, null, loader, null);
}
/**
* Removes this CtClass
object from the
* ClassPool
.
* After this method is called, any method cannot be called on the
* removed CtClass
object.
*
*
* If get()
in ClassPool
is called
* with the name of the removed method,
* the ClassPool
will read the class file again
* and constructs another CtClass
object representing
* the same class.
*/
public void detach(){
ClassPool cp = getClassPool();
CtClass obj = cp.removeCached(getName());
if (obj != this){
cp.cacheCtClass(getName(), obj, false);
}
}
/**
* Disallows (or allows) automatically pruning this CtClass
* object.
*
*
* Javassist can automatically prune a CtClass
object
* when toBytecode()
(or toClass()
,
* writeFile()
) is called.
* Since a ClassPool
holds all instances of CtClass
* even after toBytecode()
(or toClass()
,
* writeFile()
) is called, pruning may significantly
* save memory consumption.
*
*
* If ClassPool.doPruning
is true, the automatic pruning
* is on by default. Otherwise, it is off. The default value of
* ClassPool.doPruning
is false.
*
* @param stop
* disallow pruning if true. Otherwise, allow.
* @return the previous status of pruning. true if pruning is already stopped.
*
* @see #detach()
* @see #prune()
* @see ClassPool#doPruning
*/
public boolean stopPruning(boolean stop){
return true;
}
/**
* Discards unnecessary attributes, in particular,
* CodeAttribute
s (method bodies) of the class,
* to minimize the memory footprint.
* After calling this method, the class is read only.
* It cannot be modified any more.
* Furthermore, toBytecode()
,
* writeFile()
, toClass()
,
* or instrument()
cannot be called.
* However, the method names and signatures in the class etc.
* are still accessible.
*
*
* toBytecode()
, writeFile()
, and
* toClass()
internally call this method if
* automatic pruning is on.
*
*
* According to some experiments, pruning does not really reduce
* memory consumption. Only about 20%. Since pruning takes time,
* it might not pay off. So the automatic pruning is off by default.
*
* @see #stopPruning(boolean)
* @see #detach()
* @see ClassPool#doPruning
*
* @see #toBytecode()
* @see #toClass(Class)
* @see #writeFile()
* @see #instrument(CodeConverter)
* @see #instrument(ExprEditor)
*/
public void prune(){
}
/*
* Called by get() in ClassPool.
* CtClassType overrides this method.
*/
void incGetCounter(){
}
/**
* If this method is called, the class file will be
* rebuilt when it is finally generated by
* toBytecode()
and writeFile()
.
* For a performance reason, the symbol table of the
* class file may contain unused entries, for example,
* after a method or a filed is deleted.
* This method
* removes those unused entries. This removal will
* minimize the size of the class file.
*
* @since 3.8.1
*/
public void rebuildClassFile(){
}
/**
* Converts this class to a class file.
* Once this method is called, further modifications are not
* possible any more.
*
* @return the contents of the class file.
*/
public byte[] toBytecode() throws IOException,CannotCompileException{
ByteArrayOutputStream barray = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(barray);
try{
toBytecode(out);
}finally{
out.close();
}
return barray.toByteArray();
}
/**
* Writes a class file represented by this CtClass
* object in the current directory.
* Once this method is called, further modifications are not
* possible any more.
*
* @see #debugWriteFile()
*/
public void writeFile() throws NotFoundException,IOException,CannotCompileException{
writeFile(".");
}
/**
* Writes a class file represented by this CtClass
* object on a local disk.
* Once this method is called, further modifications are not
* possible any more.
*
* @param directoryName
* it must end without a directory separator.
* @see #debugWriteFile(String)
*/
public void writeFile(String directoryName) throws CannotCompileException,IOException{
DataOutputStream out = makeFileOutput(directoryName);
try{
toBytecode(out);
}finally{
out.close();
}
}
protected DataOutputStream makeFileOutput(String directoryName){
String classname = getName();
String filename = directoryName + File.separatorChar + classname.replace('.', File.separatorChar) + ".class";
int pos = filename.lastIndexOf(File.separatorChar);
if (pos > 0){
String dir = filename.substring(0, pos);
if (!dir.equals(".")){
new File(dir).mkdirs();
}
}
return new DataOutputStream(new BufferedOutputStream(new DelayedFileOutputStream(filename)));
}
/**
* Writes a class file as writeFile()
does although this
* method does not prune or freeze the class after writing the class
* file. Note that, once writeFile()
or toBytecode()
* is called, it cannot be called again since the class is pruned and frozen.
* This method would be useful for debugging.
*/
public void debugWriteFile(){
debugWriteFile(".");
}
/**
* Writes a class file as writeFile()
does although this
* method does not prune or freeze the class after writing the class
* file. Note that, once writeFile()
or toBytecode()
* is called, it cannot be called again since the class is pruned and frozen.
* This method would be useful for debugging.
*
* @param directoryName
* it must end without a directory separator.
*/
public void debugWriteFile(String directoryName){
try{
boolean p = stopPruning(true);
writeFile(directoryName);
defrost();
stopPruning(p);
}catch (Exception e){
throw new RuntimeException(e);
}
}
static class DelayedFileOutputStream extends OutputStream{
private FileOutputStream file;
private final String filename;
DelayedFileOutputStream(String name){
file = null;
filename = name;
}
private void init() throws IOException{
if (file == null){
file = new FileOutputStream(filename);
}
}
@Override
public void write(int b) throws IOException{
init();
file.write(b);
}
@Override
public void write(byte[] b) throws IOException{
init();
file.write(b);
}
@Override
public void write(byte[] b,int off,int len) throws IOException{
init();
file.write(b, off, len);
}
@Override
public void flush() throws IOException{
init();
file.flush();
}
@Override
public void close() throws IOException{
init();
file.close();
}
}
/**
* Converts this class to a class file.
* Once this method is called, further modifications are not
* possible any more.
*
*
* This method dose not close the output stream in the end.
*
* @param out
* the output stream that a class file is written to.
*/
public void toBytecode(DataOutputStream out) throws CannotCompileException,IOException{
throw new CannotCompileException("not a class");
}
/**
* Makes a unique member name. This method guarantees that
* the returned name is not used as a prefix of any methods
* or fields visible in this class.
* If the returned name is XYZ, then any method or field names
* in this class do not start with XYZ.
*
* @param prefix
* the prefix of the member name.
*/
public String makeUniqueName(String prefix){
throw new RuntimeException("not available in " + getName());
}
/*
* Invoked from ClassPool#compress().
* This method is overridden by CtClassType.
*/
void compress(){
}
}