📄 ctclasstype.java
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 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. * * 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 javassist;import java.io.BufferedInputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.URL;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashMap;import java.util.Hashtable;import java.util.List;import java.util.Set;import javassist.bytecode.AccessFlag;import javassist.bytecode.AttributeInfo;import javassist.bytecode.AnnotationsAttribute;import javassist.bytecode.BadBytecode;import javassist.bytecode.Bytecode;import javassist.bytecode.ClassFile;import javassist.bytecode.CodeAttribute;import javassist.bytecode.ConstantAttribute;import javassist.bytecode.CodeIterator;import javassist.bytecode.ConstPool;import javassist.bytecode.Descriptor;import javassist.bytecode.EnclosingMethodAttribute;import javassist.bytecode.FieldInfo;import javassist.bytecode.InnerClassesAttribute;import javassist.bytecode.MethodInfo;import javassist.bytecode.ParameterAnnotationsAttribute;import javassist.bytecode.annotation.Annotation;import javassist.compiler.AccessorMaker;import javassist.compiler.CompileError;import javassist.compiler.Javac;import javassist.expr.ExprEditor;/** * Class types. */class CtClassType extends CtClass { ClassPool classPool; boolean wasChanged; private boolean wasFrozen; boolean wasPruned; boolean memberRemoved; ClassFile classfile; private CtMember fieldsCache; private CtMember methodsCache; private CtMember constructorsCache; private CtConstructor classInitializerCache; private AccessorMaker accessors; private FieldInitLink fieldInitializers; private Hashtable hiddenMethods; // must be synchronous private int uniqueNumberSeed; private boolean doPruning = ClassPool.doPruning; int getCounter; private static int readCounter = 0; private static final int READ_THRESHOLD = 100; // see getClassFile2() CtClassType(String name, ClassPool cp) { super(name); classPool = cp; wasChanged = wasFrozen = wasPruned = memberRemoved = false; classfile = null; accessors = null; fieldInitializers = null; hiddenMethods = null; uniqueNumberSeed = 0; eraseCache(); getCounter = 0; } CtClassType(InputStream ins, ClassPool cp) throws IOException { this((String)null, cp); classfile = new ClassFile(new DataInputStream(ins)); qualifiedName = classfile.getName(); } protected void extendToString(StringBuffer buffer) { if (wasChanged) buffer.append("changed "); if (wasFrozen) buffer.append("frozen "); if (wasPruned) buffer.append("pruned "); buffer.append(Modifier.toString(getModifiers())); buffer.append(" class "); buffer.append(getName()); try { CtClass ext = getSuperclass(); if (ext != null) { String name = ext.getName(); if (!name.equals("java.lang.Object")) buffer.append(" extends " + ext.getName()); } } catch (NotFoundException e) { buffer.append(" extends ??"); } try { CtClass[] intf = getInterfaces(); if (intf.length > 0) buffer.append(" implements "); for (int i = 0; i < intf.length; ++i) { buffer.append(intf[i].getName()); buffer.append(", "); } } catch (NotFoundException e) { buffer.append(" extends ??"); } CtMember field = getFieldsCache(); buffer.append(" fields="); while (field != null) { buffer.append(field); buffer.append(", "); field = field.next; } CtMember c = getConstructorsCache(); buffer.append(" constructors="); while (c != null) { buffer.append(c); buffer.append(", "); c = c.next; } CtMember m = getMethodsCache(); buffer.append(" methods="); while (m != null) { buffer.append(m); buffer.append(", "); m = m.next; } } protected void eraseCache() { fieldsCache = null; constructorsCache = null; classInitializerCache = null; methodsCache = null; } public AccessorMaker getAccessorMaker() { if (accessors == null) accessors = new AccessorMaker(this); return accessors; } public ClassFile getClassFile2() { if (classfile != null) return classfile; if (readCounter++ > READ_THRESHOLD && ClassPool.releaseUnmodifiedClassFile) { releaseClassFiles(); readCounter = 0; } InputStream fin = null; try { fin = classPool.openClassfile(getName()); if (fin == null) throw new NotFoundException(getName()); fin = new BufferedInputStream(fin); classfile = new ClassFile(new DataInputStream(fin)); if (!classfile.getName().equals(qualifiedName)) throw new RuntimeException("cannot find " + qualifiedName + ": " + classfile.getName() + " found in " + qualifiedName.replace('.', '/') + ".class"); return classfile; } catch (NotFoundException e) { throw new RuntimeException(e.toString()); } catch (IOException e) { throw new RuntimeException(e.toString()); } finally { if (fin != null) try { fin.close(); } catch (IOException e) {} } } /* Inherited from CtClass. Called by get() in ClassPool. * * @see javassist.CtClass#incGetCounter() */ void incGetCounter() { ++getCounter; } /** * Releases the class files and cached CtBehaviors * of the CtClasses that have not been recently used * if they are unmodified. */ private void releaseClassFiles() { Enumeration e = classPool.classes.elements(); while (e.hasMoreElements()) { Object obj = e.nextElement(); if (obj instanceof CtClassType) { CtClassType cct = (CtClassType)obj; if (cct.getCounter < 2 && !cct.isModified()) { cct.eraseCache(); cct.classfile = null; } cct.getCounter = 0; } } } public ClassPool getClassPool() { return classPool; } void setClassPool(ClassPool cp) { classPool = cp; } public URL getURL() throws NotFoundException { URL url = classPool.find(getName()); if (url == null) throw new NotFoundException(getName()); else return url; } public boolean isModified() { return wasChanged; } public boolean isFrozen() { return wasFrozen; } void freeze() { wasFrozen = true; } void checkModify() throws RuntimeException { if (isFrozen()) { String msg = getName() + " class is frozen"; if (wasPruned) msg += " and pruned"; throw new RuntimeException(msg); } wasChanged = true; } public void defrost() { checkPruned("defrost"); wasFrozen = false; } public boolean subtypeOf(CtClass clazz) throws NotFoundException { int i; String cname = clazz.getName(); if (this == clazz || getName().equals(cname)) return true; ClassFile file = getClassFile2(); String supername = file.getSuperclass(); if (supername != null && supername.equals(cname)) return true; String[] ifs = file.getInterfaces(); int num = ifs.length; for (i = 0; i < num; ++i) if (ifs[i].equals(cname)) return true; if (supername != null && classPool.get(supername).subtypeOf(clazz)) return true; for (i = 0; i < num; ++i) if (classPool.get(ifs[i]).subtypeOf(clazz)) return true; return false; } public void setName(String name) throws RuntimeException { String oldname = getName(); if (name.equals(oldname)) return; // check this in advance although classNameChanged() below does. classPool.checkNotFrozen(name); ClassFile cf = getClassFile2(); super.setName(name); cf.setName(name); eraseCache(); classPool.classNameChanged(oldname, this); } public void replaceClassName(ClassMap classnames) throws RuntimeException { String oldClassName = getName(); String newClassName = (String)classnames.get(Descriptor.toJvmName(oldClassName)); if (newClassName != null) { newClassName = Descriptor.toJavaName(newClassName); // check this in advance although classNameChanged() below does. classPool.checkNotFrozen(newClassName); } super.replaceClassName(classnames); ClassFile cf = getClassFile2(); cf.renameClass(classnames); eraseCache(); if (newClassName != null) { super.setName(newClassName); classPool.classNameChanged(oldClassName, this); } } public void replaceClassName(String oldname, String newname) throws RuntimeException { String thisname = getName(); if (thisname.equals(oldname)) setName(newname); else { super.replaceClassName(oldname, newname); getClassFile2().renameClass(oldname, newname); eraseCache(); } } public boolean isInterface() { return Modifier.isInterface(getModifiers()); } public boolean isAnnotation() { return Modifier.isAnnotation(getModifiers()); } public boolean isEnum() { return Modifier.isEnum(getModifiers()); } public int getModifiers() { ClassFile cf = getClassFile2(); int acc = cf.getAccessFlags(); acc = AccessFlag.clear(acc, AccessFlag.SUPER); int inner = cf.getInnerAccessFlags(); if (inner != -1 && (inner & AccessFlag.STATIC) != 0) acc |= AccessFlag.STATIC; return AccessFlag.toModifier(acc); } public CtClass[] getNestedClasses() throws NotFoundException { ClassFile cf = getClassFile2();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -