From b28caee37389d844b4d9c537f031a5bc294c89c0 Mon Sep 17 00:00:00 2001 From: patriot1burke Date: Thu, 9 Dec 2004 22:37:15 +0000 Subject: [PATCH] methodinfos are not equal for some reason. git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@149 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- src/main/javassist/bytecode/MethodInfo.java | 756 ++++++++++---------- src/main/javassist/expr/Expr.java | 470 ++++++------ 2 files changed, 661 insertions(+), 565 deletions(-) diff --git a/src/main/javassist/bytecode/MethodInfo.java b/src/main/javassist/bytecode/MethodInfo.java index 2e1e4fed..9d434e16 100644 --- a/src/main/javassist/bytecode/MethodInfo.java +++ b/src/main/javassist/bytecode/MethodInfo.java @@ -28,364 +28,400 @@ import java.util.Map; * @see javassist.CtMethod#getMethodInfo() * @see javassist.CtConstructor#getMethodInfo() */ -public final class MethodInfo { - ConstPool constPool; - int accessFlags; - int name; - int descriptor; - LinkedList attribute; // may be null - - /** - * The name of constructors: <init>. - */ - public static final String nameInit = ""; - - /** - * The name of class initializer (static initializer): - * <clinit>. - */ - public static final String nameClinit = ""; - - private MethodInfo(ConstPool cp) { - constPool = cp; - attribute = null; - } - - /** - * Constructs a method_info structure. - * The initial value of access_flags is zero. - * - * @param cp a constant pool table - * @param methodname method name - * @param desc method descriptor - * @see Descriptor - */ - public MethodInfo(ConstPool cp, String methodname, String desc) { - this(cp); - accessFlags = 0; - name = cp.addUtf8Info(methodname); - descriptor = constPool.addUtf8Info(desc); - } - - MethodInfo(ConstPool cp, DataInputStream in) throws IOException { - this(cp); - read(in); - } - - /** - * Constructs a copy of method_info structure. - * Class names appearing in the source method_info - * are renamed according to classnameMap. - * - *

Note: only Code and Exceptions - * attributes are copied from the source. The other attributes - * are ignored. - * - * @param cp a constant pool table - * @param methodname a method name - * @param src a source method_info - * @param classnameMap specifies pairs of replaced and substituted - * name. - * @see Descriptor - */ - public MethodInfo(ConstPool cp, String methodname, MethodInfo src, - Map classnameMap) throws BadBytecode - { - this(cp); - read(src, methodname, classnameMap); - } - - void prune(ConstPool cp) { - attribute = null; - name = cp.addUtf8Info(getName()); - descriptor = cp.addUtf8Info(getDescriptor()); - constPool = cp; - } - - /** - * Returns a method name. - */ - public String getName() { - return constPool.getUtf8Info(name); - } - - /** - * Sets a method name. - */ - public void setName(String newName) { - name = constPool.addUtf8Info(newName); - } - - /** - * Returns true if this is not a constructor or a class initializer - * (static initializer). - */ - public boolean isMethod() { - String n = getName(); - return !n.equals(nameInit) && !n.equals(nameClinit); - } - - /** - * Returns a constant pool table used by this method. - */ - public ConstPool getConstPool() { - return constPool; - } - - /** - * Returns true if this is a constructor. - */ - public boolean isConstructor() { - return getName().equals(nameInit); - } - - /** - * Returns true if this is a class initializer (static initializer). - */ - public boolean isStaticInitializer() { - return getName().equals(nameClinit); - } - - /** - * Returns access flags. - * - * @see AccessFlag - */ - public int getAccessFlags() { - return accessFlags; - } - - /** - * Sets access flags. - * - * @see AccessFlag - */ - public void setAccessFlags(int acc) { - accessFlags = acc; - } - - /** - * Returns a method descriptor. - * - * @see Descriptor - */ - public String getDescriptor() { - return constPool.getUtf8Info(descriptor); - } - - /** - * Sets a method descriptor. - * - * @see Descriptor - */ - public void setDescriptor(String desc) { - if (!desc.equals(getDescriptor())) - descriptor = constPool.addUtf8Info(desc); - } - - /** - * Returns all the attributes. - * A new element can be added to the returned list - * and an existing element can be removed from the list. - * - * @return a list of AttributeInfo objects. - * @see AttributeInfo - */ - public List getAttributes() { - if (attribute == null) - attribute = new LinkedList(); - - return attribute; - } - - /** - * Returns the attribute with the specified name. - * If it is not found, this method returns null. - * - * @param name attribute name - * @return an AttributeInfo object or null. - */ - public AttributeInfo getAttribute(String name) { - return AttributeInfo.lookup(attribute, name); - } - - /** - * Appends an attribute. If there is already an attribute with - * the same name, the new one substitutes for it. - */ - public void addAttribute(AttributeInfo info) { - if (attribute == null) - attribute = new LinkedList(); - - AttributeInfo.remove(attribute, info.getName()); - attribute.add(info); - } - - /** - * Returns an Exceptions attribute. - * - * @return an Exceptions attribute - * or null if it is not specified. - */ - public ExceptionsAttribute getExceptionsAttribute() { - AttributeInfo info - = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag); - return (ExceptionsAttribute)info; - } - - /** - * Returns a Code attribute. - * - * @return a Code attribute - * or null if it is not specified. - */ - public CodeAttribute getCodeAttribute() { - AttributeInfo info - = AttributeInfo.lookup(attribute, CodeAttribute.tag); - return (CodeAttribute)info; - } - - /** - * Removes an Exception attribute. - */ - public void removeExceptionsAttribute() { - AttributeInfo.remove(attribute, ExceptionsAttribute.tag); - } - - /** - * Adds an Exception attribute. - * - *

The added attribute must share the same constant pool table - * as this method_info structure. - */ - public void setExceptionsAttribute(ExceptionsAttribute cattr) { - removeExceptionsAttribute(); - if (attribute == null) - attribute = new LinkedList(); - - attribute.add(cattr); - } - - /** - * Removes a Code attribute. - */ - public void removeCodeAttribute() { - AttributeInfo.remove(attribute, CodeAttribute.tag); - } - - /** - * Adds a Code attribute. - * - *

The added attribute must share the same constant pool table - * as this method_info structure. - */ - public void setCodeAttribute(CodeAttribute cattr) { - removeCodeAttribute(); - if (attribute == null) - attribute = new LinkedList(); - - attribute.add(cattr); - } - - /** - * Returns the line number of the source line corresponding to the - * specified bytecode contained in this method. - * - * @param pos the position of the bytecode (>= 0). - * an index into the code array. - * @return -1 if this information is not available. - */ - public int getLineNumber(int pos) { - CodeAttribute ca = getCodeAttribute(); - if (ca == null) - return -1; - - LineNumberAttribute ainfo = - (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); - if (ainfo == null) - return -1; - - return ainfo.toLineNumber(pos); - } - - /** - * Changes a super constructor called by this constructor. - * - *

This method modifies a call to super(), - * which should be at the - * head of a constructor body, so that a constructor in a different - * super class is called. This method does not change actural - * parameters. Hence the new super class must have a constructor - * with the same signature as the original one. - * - *

This method should be called when the super class - * of the class declaring this method is changed. - * - *

This method does not perform anything unless this - * MethodInfo represents a constructor. - * - * @param superclass the new super class - */ - public void setSuperclass(String superclass) throws BadBytecode { - if (!isConstructor()) - return; - - CodeAttribute ca = getCodeAttribute(); - byte[] code = ca.getCode(); - CodeIterator iterator = ca.iterator(); - int pos = iterator.skipSuperConstructor(); - if (pos >= 0) { // not this() - ConstPool cp = constPool; - int mref = ByteArray.readU16bit(code, pos + 1); - int nt = cp.getMethodrefNameAndType(mref); - int sc = cp.addClassInfo(superclass); - int mref2 = cp.addMethodrefInfo(sc, nt); - ByteArray.write16bit(mref2, code, pos + 1); - } - } - - private void read(MethodInfo src, String methodname, Map classnames) - throws BadBytecode - { - ConstPool destCp = constPool; - accessFlags = src.accessFlags; - name = destCp.addUtf8Info(methodname); - - ConstPool srcCp = src.constPool; - String desc = srcCp.getUtf8Info(src.descriptor); - String desc2 = Descriptor.rename(desc, classnames); - descriptor = destCp.addUtf8Info(desc2); - - attribute = new LinkedList(); - ExceptionsAttribute eattr = src.getExceptionsAttribute(); - if (eattr != null) - attribute.add(eattr.copy(destCp, classnames)); - - CodeAttribute cattr = src.getCodeAttribute(); - if (cattr != null) - attribute.add(cattr.copy(destCp, classnames)); - } - - private void read(DataInputStream in) throws IOException { - accessFlags = in.readUnsignedShort(); - name = in.readUnsignedShort(); - descriptor = in.readUnsignedShort(); - int n = in.readUnsignedShort(); - attribute = new LinkedList(); - for (int i = 0; i < n; ++i) - attribute.add(AttributeInfo.read(constPool, in)); - } - - void write(DataOutputStream out) throws IOException { - out.writeShort(accessFlags); - out.writeShort(name); - out.writeShort(descriptor); - - if (attribute == null) - out.writeShort(0); - else { - out.writeShort(attribute.size()); - AttributeInfo.writeAll(attribute, out); - } - } +public final class MethodInfo +{ + ConstPool constPool; + int accessFlags; + int name; + int descriptor; + LinkedList attribute; // may be null + public Exception created = new Exception(); + + /** + * The name of constructors: <init>. + */ + public static final String nameInit = ""; + + /** + * The name of class initializer (static initializer): + * <clinit>. + */ + public static final String nameClinit = ""; + + private MethodInfo(ConstPool cp) + { + constPool = cp; + attribute = null; + } + + /** + * Constructs a method_info structure. + * The initial value of access_flags is zero. + * + * @param cp a constant pool table + * @param methodname method name + * @param desc method descriptor + * @see Descriptor + */ + public MethodInfo(ConstPool cp, String methodname, String desc) + { + this(cp); + accessFlags = 0; + name = cp.addUtf8Info(methodname); + descriptor = constPool.addUtf8Info(desc); + } + + MethodInfo(ConstPool cp, DataInputStream in) throws IOException + { + this(cp); + read(in); + } + + /** + * Constructs a copy of method_info structure. + * Class names appearing in the source method_info + * are renamed according to classnameMap. + *

+ *

Note: only Code and Exceptions + * attributes are copied from the source. The other attributes + * are ignored. + * + * @param cp a constant pool table + * @param methodname a method name + * @param src a source method_info + * @param classnameMap specifies pairs of replaced and substituted + * name. + * @see Descriptor + */ + public MethodInfo(ConstPool cp, String methodname, MethodInfo src, + Map classnameMap) throws BadBytecode + { + this(cp); + read(src, methodname, classnameMap); + } + + public String toString() + { + return constPool.getUtf8Info(name) + " " + constPool.getUtf8Info(descriptor); + } + + void prune(ConstPool cp) + { + attribute = null; + name = cp.addUtf8Info(getName()); + descriptor = cp.addUtf8Info(getDescriptor()); + constPool = cp; + } + + /** + * Returns a method name. + */ + public String getName() + { + return constPool.getUtf8Info(name); + } + + /** + * Sets a method name. + */ + public void setName(String newName) + { + name = constPool.addUtf8Info(newName); + } + + /** + * Returns true if this is not a constructor or a class initializer + * (static initializer). + */ + public boolean isMethod() + { + String n = getName(); + return !n.equals(nameInit) && !n.equals(nameClinit); + } + + /** + * Returns a constant pool table used by this method. + */ + public ConstPool getConstPool() + { + return constPool; + } + + /** + * Returns true if this is a constructor. + */ + public boolean isConstructor() + { + return getName().equals(nameInit); + } + + /** + * Returns true if this is a class initializer (static initializer). + */ + public boolean isStaticInitializer() + { + return getName().equals(nameClinit); + } + + /** + * Returns access flags. + * + * @see AccessFlag + */ + public int getAccessFlags() + { + return accessFlags; + } + + /** + * Sets access flags. + * + * @see AccessFlag + */ + public void setAccessFlags(int acc) + { + accessFlags = acc; + } + + /** + * Returns a method descriptor. + * + * @see Descriptor + */ + public String getDescriptor() + { + return constPool.getUtf8Info(descriptor); + } + + /** + * Sets a method descriptor. + * + * @see Descriptor + */ + public void setDescriptor(String desc) + { + if (!desc.equals(getDescriptor())) + descriptor = constPool.addUtf8Info(desc); + } + + /** + * Returns all the attributes. + * A new element can be added to the returned list + * and an existing element can be removed from the list. + * + * @return a list of AttributeInfo objects. + * @see AttributeInfo + */ + public List getAttributes() + { + if (attribute == null) + attribute = new LinkedList(); + + return attribute; + } + + /** + * Returns the attribute with the specified name. + * If it is not found, this method returns null. + * + * @param name attribute name + * @return an AttributeInfo object or null. + */ + public AttributeInfo getAttribute(String name) + { + return AttributeInfo.lookup(attribute, name); + } + + /** + * Appends an attribute. If there is already an attribute with + * the same name, the new one substitutes for it. + */ + public void addAttribute(AttributeInfo info) + { + if (attribute == null) + attribute = new LinkedList(); + + AttributeInfo.remove(attribute, info.getName()); + attribute.add(info); + } + + /** + * Returns an Exceptions attribute. + * + * @return an Exceptions attribute + * or null if it is not specified. + */ + public ExceptionsAttribute getExceptionsAttribute() + { + AttributeInfo info + = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag); + return (ExceptionsAttribute) info; + } + + /** + * Returns a Code attribute. + * + * @return a Code attribute + * or null if it is not specified. + */ + public CodeAttribute getCodeAttribute() + { + AttributeInfo info + = AttributeInfo.lookup(attribute, CodeAttribute.tag); + return (CodeAttribute) info; + } + + /** + * Removes an Exception attribute. + */ + public void removeExceptionsAttribute() + { + AttributeInfo.remove(attribute, ExceptionsAttribute.tag); + } + + /** + * Adds an Exception attribute. + *

+ *

The added attribute must share the same constant pool table + * as this method_info structure. + */ + public void setExceptionsAttribute(ExceptionsAttribute cattr) + { + removeExceptionsAttribute(); + if (attribute == null) + attribute = new LinkedList(); + + attribute.add(cattr); + } + + /** + * Removes a Code attribute. + */ + public void removeCodeAttribute() + { + AttributeInfo.remove(attribute, CodeAttribute.tag); + } + + /** + * Adds a Code attribute. + *

+ *

The added attribute must share the same constant pool table + * as this method_info structure. + */ + public void setCodeAttribute(CodeAttribute cattr) + { + removeCodeAttribute(); + if (attribute == null) + attribute = new LinkedList(); + + attribute.add(cattr); + } + + /** + * Returns the line number of the source line corresponding to the + * specified bytecode contained in this method. + * + * @param pos the position of the bytecode (>= 0). + * an index into the code array. + * @return -1 if this information is not available. + */ + public int getLineNumber(int pos) + { + CodeAttribute ca = getCodeAttribute(); + if (ca == null) + return -1; + + LineNumberAttribute ainfo = + (LineNumberAttribute) ca.getAttribute(LineNumberAttribute.tag); + if (ainfo == null) + return -1; + + return ainfo.toLineNumber(pos); + } + + /** + * Changes a super constructor called by this constructor. + *

+ *

This method modifies a call to super(), + * which should be at the + * head of a constructor body, so that a constructor in a different + * super class is called. This method does not change actural + * parameters. Hence the new super class must have a constructor + * with the same signature as the original one. + *

+ *

This method should be called when the super class + * of the class declaring this method is changed. + *

+ *

This method does not perform anything unless this + * MethodInfo represents a constructor. + * + * @param superclass the new super class + */ + public void setSuperclass(String superclass) throws BadBytecode + { + if (!isConstructor()) + return; + + CodeAttribute ca = getCodeAttribute(); + byte[] code = ca.getCode(); + CodeIterator iterator = ca.iterator(); + int pos = iterator.skipSuperConstructor(); + if (pos >= 0) + { // not this() + ConstPool cp = constPool; + int mref = ByteArray.readU16bit(code, pos + 1); + int nt = cp.getMethodrefNameAndType(mref); + int sc = cp.addClassInfo(superclass); + int mref2 = cp.addMethodrefInfo(sc, nt); + ByteArray.write16bit(mref2, code, pos + 1); + } + } + + private void read(MethodInfo src, String methodname, Map classnames) + throws BadBytecode + { + ConstPool destCp = constPool; + accessFlags = src.accessFlags; + name = destCp.addUtf8Info(methodname); + + ConstPool srcCp = src.constPool; + String desc = srcCp.getUtf8Info(src.descriptor); + String desc2 = Descriptor.rename(desc, classnames); + descriptor = destCp.addUtf8Info(desc2); + + attribute = new LinkedList(); + ExceptionsAttribute eattr = src.getExceptionsAttribute(); + if (eattr != null) + attribute.add(eattr.copy(destCp, classnames)); + + CodeAttribute cattr = src.getCodeAttribute(); + if (cattr != null) + attribute.add(cattr.copy(destCp, classnames)); + } + + private void read(DataInputStream in) throws IOException + { + accessFlags = in.readUnsignedShort(); + name = in.readUnsignedShort(); + descriptor = in.readUnsignedShort(); + int n = in.readUnsignedShort(); + attribute = new LinkedList(); + for (int i = 0; i < n; ++i) + attribute.add(AttributeInfo.read(constPool, in)); + } + + void write(DataOutputStream out) throws IOException + { + out.writeShort(accessFlags); + out.writeShort(name); + out.writeShort(descriptor); + + if (attribute == null) + out.writeShort(0); + else + { + out.writeShort(attribute.size()); + AttributeInfo.writeAll(attribute, out); + } + } } diff --git a/src/main/javassist/expr/Expr.java b/src/main/javassist/expr/Expr.java index 3c99b1fc..8d2b75ab 100644 --- a/src/main/javassist/expr/Expr.java +++ b/src/main/javassist/expr/Expr.java @@ -15,216 +15,276 @@ package javassist.expr; -import javassist.*; -import javassist.bytecode.*; -import javassist.compiler.*; -import java.util.LinkedList; +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtBehavior; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtPrimitiveType; +import javassist.NotFoundException; +import javassist.bytecode.AccessFlag; +import javassist.bytecode.BadBytecode; +import javassist.bytecode.Bytecode; +import javassist.bytecode.ClassFile; +import javassist.bytecode.CodeAttribute; +import javassist.bytecode.CodeIterator; +import javassist.bytecode.ConstPool; +import javassist.bytecode.ExceptionTable; +import javassist.bytecode.ExceptionsAttribute; +import javassist.bytecode.MethodInfo; +import javassist.bytecode.Opcode; +import javassist.compiler.Javac; + import java.util.Iterator; +import java.util.LinkedList; /** * Expression. */ -public abstract class Expr implements Opcode { - int currentPos; - CodeIterator iterator; - CtClass thisClass; - MethodInfo thisMethod; - - boolean edited; - int maxLocals, maxStack; - - static final String javaLangObject = "java.lang.Object"; - - /** - * Undocumented constructor. Do not use; internal-use only. - */ - protected Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { - currentPos = pos; - iterator = i; - thisClass = declaring; - thisMethod = m; - } - - protected final ConstPool getConstPool() { - return thisMethod.getConstPool(); - } - - protected final boolean edited() { return edited; } - - protected final int locals() { return maxLocals; } - - protected final int stack() { return maxStack; } - - /** - * Returns true if this method is static. - */ - protected final boolean withinStatic() { - return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0; - } - - /** - * Returns the constructor or method containing the expression. - */ - public CtBehavior where() { - MethodInfo mi = thisMethod; - CtBehavior[] cb = thisClass.getDeclaredBehaviors(); - for (int i = cb.length - 1; i >= 0; --i) - if (cb[i].getMethodInfo2() == mi) - return cb[i]; - - CtConstructor init = thisClass.getClassInitializer(); - if (init.getMethodInfo2() == mi) - return init; - - throw new RuntimeException("fatal: not found"); - } - - /** - * Returns the list of exceptions that the expression may throw. - * This list includes both the exceptions that the try-catch statements - * including the expression can catch and the exceptions that - * the throws declaration allows the method to throw. - */ - public CtClass[] mayThrow() { - ClassPool pool = thisClass.getClassPool(); - ConstPool cp = thisMethod.getConstPool(); - LinkedList list = new LinkedList(); - try { - CodeAttribute ca = thisMethod.getCodeAttribute(); - ExceptionTable et = ca.getExceptionTable(); - int pos = currentPos; - int n = et.size(); - for (int i = 0; i < n; ++i) - if (et.startPc(i) <= pos && pos < et.endPc(i)) { - int t = et.catchType(i); - if (t > 0) - try { - addClass(list, pool.get(cp.getClassInfo(t))); - } - catch (NotFoundException e) {} - } - } - catch (NullPointerException e) {} - - ExceptionsAttribute ea = thisMethod.getExceptionsAttribute(); - if (ea != null) { - String[] exceptions = ea.getExceptions(); - if (exceptions != null) { - int n = exceptions.length; - for (int i = 0; i < n; ++i) - try { - addClass(list, pool.get(exceptions[i])); - } - catch (NotFoundException e) {} +public abstract class Expr implements Opcode +{ + int currentPos; + CodeIterator iterator; + CtClass thisClass; + MethodInfo thisMethod; + + boolean edited; + int maxLocals, maxStack; + + static final String javaLangObject = "java.lang.Object"; + + /** + * Undocumented constructor. Do not use; internal-use only. + */ + protected Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) + { + currentPos = pos; + iterator = i; + thisClass = declaring; + thisMethod = m; + } + + protected final ConstPool getConstPool() + { + return thisMethod.getConstPool(); + } + + protected final boolean edited() + { + return edited; + } + + protected final int locals() + { + return maxLocals; + } + + protected final int stack() + { + return maxStack; + } + + /** + * Returns true if this method is static. + */ + protected final boolean withinStatic() + { + return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0; + } + + /** + * Returns the constructor or method containing the expression. + */ + public CtBehavior where() + { + MethodInfo mi = thisMethod; + CtBehavior[] cb = thisClass.getDeclaredBehaviors(); + for (int i = cb.length - 1; i >= 0; --i) + if (cb[i].getMethodInfo2() == mi) + return cb[i]; + + CtConstructor init = thisClass.getClassInitializer(); + if (init != null && init.getMethodInfo2() == mi) + return init; + + // todo REVISIT I needed to add this because for some reason mi != cb[i] + for (int i = cb.length - 1; i >= 0; --i) + { + if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) && thisMethod.getDescriptor().equals(cb[i].getMethodInfo2().getDescriptor())) + { + return cb[i]; + } + } + + String msg = "fatal: not found"; + throw new RuntimeException(msg); + } + + /** + * Returns the list of exceptions that the expression may throw. + * This list includes both the exceptions that the try-catch statements + * including the expression can catch and the exceptions that + * the throws declaration allows the method to throw. + */ + public CtClass[] mayThrow() + { + ClassPool pool = thisClass.getClassPool(); + ConstPool cp = thisMethod.getConstPool(); + LinkedList list = new LinkedList(); + try + { + CodeAttribute ca = thisMethod.getCodeAttribute(); + ExceptionTable et = ca.getExceptionTable(); + int pos = currentPos; + int n = et.size(); + for (int i = 0; i < n; ++i) + if (et.startPc(i) <= pos && pos < et.endPc(i)) + { + int t = et.catchType(i); + if (t > 0) + try + { + addClass(list, pool.get(cp.getClassInfo(t))); + } + catch (NotFoundException e) + { + } } - } - - return (CtClass[])list.toArray(new CtClass[list.size()]); - } - - private static void addClass(LinkedList list, CtClass c) { - Iterator it = list.iterator(); - while (it.hasNext()) - if (it.next() == c) - return; - - list.add(c); - } - - /** - * Returns the index of the bytecode corresponding to the - * expression. - * It is the index into the byte array containing the Java bytecode - * that implements the method. - */ - public int indexOfBytecode() { - return currentPos; - } - - /** - * Returns the line number of the source line containing the - * expression. - * - * @return -1 if this information is not available. - */ - public int getLineNumber() { - return thisMethod.getLineNumber(currentPos); - } - - /** - * Returns the source file containing the expression. - * - * @return null if this information is not available. - */ - public String getFileName() { - ClassFile cf = thisClass.getClassFile2(); - if (cf == null) - return null; - else - return cf.getSourceFile(); - } - - static final boolean checkResultValue(CtClass retType, String prog) - throws CannotCompileException - { - /* Is $_ included in the source code? - */ - boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0); - if (!hasIt && retType != CtClass.voidType) - throw new CannotCompileException( - "the resulting value is not stored in " - + Javac.resultVarName); - - return hasIt; - } - - /* If isStaticCall is true, null is assigned to $0. So $0 must - * be declared by calling Javac.recordParams(). - * - * After executing this method, the current stack depth might - * be less than 0. - */ - static final void storeStack(CtClass[] params, boolean isStaticCall, - int regno, Bytecode bytecode) { - storeStack0(0, params.length, params, regno + 1, bytecode); - if (isStaticCall) - bytecode.addOpcode(ACONST_NULL); - - bytecode.addAstore(regno); - } - - private static void storeStack0(int i, int n, CtClass[] params, - int regno, Bytecode bytecode) { - if (i >= n) + } + catch (NullPointerException e) + { + } + + ExceptionsAttribute ea = thisMethod.getExceptionsAttribute(); + if (ea != null) + { + String[] exceptions = ea.getExceptions(); + if (exceptions != null) + { + int n = exceptions.length; + for (int i = 0; i < n; ++i) + try + { + addClass(list, pool.get(exceptions[i])); + } + catch (NotFoundException e) + { + } + } + } + + return (CtClass[]) list.toArray(new CtClass[list.size()]); + } + + private static void addClass(LinkedList list, CtClass c) + { + Iterator it = list.iterator(); + while (it.hasNext()) + if (it.next() == c) return; - else { - CtClass c = params[i]; - int size; - if (c instanceof CtPrimitiveType) - size = ((CtPrimitiveType)c).getDataSize(); - else - size = 1; - - storeStack0(i + 1, n, params, regno + size, bytecode); - bytecode.addStore(regno, c); - } - } - - protected void replace0(int pos, Bytecode bytecode, int size) - throws BadBytecode - { - byte[] code = bytecode.get(); - edited = true; - int gap = code.length - size; - for (int i = 0; i < size; ++i) - iterator.writeByte(NOP, pos + i); - - if (gap > 0) - iterator.insertGap(pos, gap); - - iterator.write(code, pos); - iterator.insert(bytecode.getExceptionTable(), pos); - maxLocals = bytecode.getMaxLocals(); - maxStack = bytecode.getMaxStack(); - } + + list.add(c); + } + + /** + * Returns the index of the bytecode corresponding to the + * expression. + * It is the index into the byte array containing the Java bytecode + * that implements the method. + */ + public int indexOfBytecode() + { + return currentPos; + } + + /** + * Returns the line number of the source line containing the + * expression. + * + * @return -1 if this information is not available. + */ + public int getLineNumber() + { + return thisMethod.getLineNumber(currentPos); + } + + /** + * Returns the source file containing the expression. + * + * @return null if this information is not available. + */ + public String getFileName() + { + ClassFile cf = thisClass.getClassFile2(); + if (cf == null) + return null; + else + return cf.getSourceFile(); + } + + static final boolean checkResultValue(CtClass retType, String prog) + throws CannotCompileException + { + /* Is $_ included in the source code? + */ + boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0); + if (!hasIt && retType != CtClass.voidType) + throw new CannotCompileException("the resulting value is not stored in " + + Javac.resultVarName); + + return hasIt; + } + + /* If isStaticCall is true, null is assigned to $0. So $0 must + * be declared by calling Javac.recordParams(). + * + * After executing this method, the current stack depth might + * be less than 0. + */ + static final void storeStack(CtClass[] params, boolean isStaticCall, + int regno, Bytecode bytecode) + { + storeStack0(0, params.length, params, regno + 1, bytecode); + if (isStaticCall) + bytecode.addOpcode(ACONST_NULL); + + bytecode.addAstore(regno); + } + + private static void storeStack0(int i, int n, CtClass[] params, + int regno, Bytecode bytecode) + { + if (i >= n) + return; + else + { + CtClass c = params[i]; + int size; + if (c instanceof CtPrimitiveType) + size = ((CtPrimitiveType) c).getDataSize(); + else + size = 1; + + storeStack0(i + 1, n, params, regno + size, bytecode); + bytecode.addStore(regno, c); + } + } + + protected void replace0(int pos, Bytecode bytecode, int size) + throws BadBytecode + { + byte[] code = bytecode.get(); + edited = true; + int gap = code.length - size; + for (int i = 0; i < size; ++i) + iterator.writeByte(NOP, pos + i); + + if (gap > 0) + iterator.insertGap(pos, gap); + + iterator.write(code, pos); + iterator.insert(bytecode.getExceptionTable(), pos); + maxLocals = bytecode.getMaxLocals(); + maxStack = bytecode.getMaxStack(); + } } -- 2.39.5