123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- /*
- * Javassist, a Java-bytecode translator toolkit.
- * Copyright (C) 1999-2003 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.bytecode;
-
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.util.List;
- import java.util.LinkedList;
- import java.util.Map;
- import javassist.CtClass;
-
- /**
- * <code>Code_attribute</code>.
- *
- * <p>To browse the <code>code</code> field of
- * a <code>Code_attribute</code> structure,
- * use <code>CodeIterator</code>.
- *
- * @see CodeIterator
- */
- public class CodeAttribute extends AttributeInfo implements Opcode {
- /**
- * The name of this attribute <code>"Code"</code>.
- */
- public static final String tag = "Code";
-
- // code[] is stored in AttributeInfo.info.
-
- private int maxStack;
- private int maxLocals;
- private ExceptionTable exceptions;
- private LinkedList attributes;
-
- /**
- * Constructs a <code>Code_attribute</code>.
- *
- * @param cp constant pool table
- * @param stack <code>max_stack</code>
- * @param locals <code>max_locals</code>
- * @param code <code>code[]</code>
- * @param etable <code>exception_table[]</code>
- */
- public CodeAttribute(ConstPool cp, int stack, int locals, byte[] code,
- ExceptionTable etable)
- {
- super(cp, tag);
- maxStack = stack;
- maxLocals = locals;
- info = code;
- exceptions = etable;
- attributes = new LinkedList();
- }
-
- /**
- * Constructs a copy of <code>Code_attribute</code>.
- * Specified class names are replaced during the copy.
- *
- * @param cp constant pool table.
- * @param src source Code attribute.
- * @param classnames pairs of replaced and substituted
- * class names.
- */
- private CodeAttribute(ConstPool cp, CodeAttribute src, Map classnames)
- throws BadBytecode
- {
- super(cp, tag);
-
- maxStack = src.getMaxStack();
- maxLocals = src.getMaxLocals();
- exceptions = src.getExceptionTable().copy(cp, classnames);
- info = src.copyCode(cp, classnames, exceptions);
- attributes = new LinkedList();
-
- /* Since an index into the source constant pool table may not
- be translated, we don't copy the attributes.
- */
- /*
- List src_attr = src.getAttributes();
- int num = src_attr.size();
- for (int i = 0; i < num; ++i) {
- AttributeInfo ai = (AttributeInfo)src_attr.get(i);
- attributes.add(ai.copy(cp, classnames));
- }
- */
- }
-
- CodeAttribute(ConstPool cp, int name_id, DataInputStream in)
- throws IOException
- {
- super(cp, name_id, (byte[])null);
- int attr_len = in.readInt();
-
- maxStack = in.readUnsignedShort();
- maxLocals = in.readUnsignedShort();
-
- int code_len = in.readInt();
- info = new byte[code_len];
- in.readFully(info);
-
- exceptions = new ExceptionTable(cp, in);
-
- attributes = new LinkedList();
- int num = in.readUnsignedShort();
- for (int i = 0; i < num; ++i)
- attributes.add(AttributeInfo.read(cp, in));
- }
-
- /**
- * Makes a copy. Class names are replaced according to the
- * given <code>Map</code> object.
- *
- * @param newCp the constant pool table used by the new copy.
- * @param classnames pairs of replaced and substituted
- * class names.
- * @exception RuntimeCopyException if a <code>BadBytecode</code>
- * exception is thrown, it is
- * converted into
- * <code>RuntimeCopyException</code>.
- *
- * @return <code>CodeAttribute</code> object.
- */
- public AttributeInfo copy(ConstPool newCp, Map classnames)
- throws RuntimeCopyException
- {
- try {
- return new CodeAttribute(newCp, this, classnames);
- }
- catch (BadBytecode e) {
- throw new RuntimeCopyException("bad bytecode. fatal?");
- }
- }
-
- /**
- * An exception that may be thrown by <code>copy()</code>
- * in <code>CodeAttribute</code>.
- */
- public static class RuntimeCopyException extends RuntimeException {
- /**
- * Constructs an exception.
- */
- public RuntimeCopyException(String s) {
- super(s);
- }
- }
-
- /**
- * Returns the length of this <code>attribute_info</code>
- * structure.
- * The returned value is <code>attribute_length + 6</code>.
- */
- public int length() {
- return 18 + info.length + exceptions.size() * 8
- + AttributeInfo.getLength(attributes);
- }
-
- void write(DataOutputStream out) throws IOException {
- out.writeShort(name); // attribute_name_index
- out.writeInt(length() - 6); // attribute_length
- out.writeShort(maxStack); // max_stack
- out.writeShort(maxLocals); // max_locals
- out.writeInt(info.length); // code_length
- out.write(info); // code
- exceptions.write(out);
- out.writeShort(attributes.size()); // attributes_count
- AttributeInfo.writeAll(attributes, out); // attributes
- }
-
- /**
- * This method is not available.
- *
- * @throws java.lang.UnsupportedOperationException always thrown.
- */
- public byte[] get() {
- throw new UnsupportedOperationException("CodeAttribute.get()");
- }
-
- /**
- * This method is not available.
- *
- * @throws java.lang.UnsupportedOperationException always thrown.
- */
- public void set(byte[] newinfo) {
- throw new UnsupportedOperationException("CodeAttribute.set()");
- }
-
- /**
- * Returns the name of the class declaring the method including
- * this code attribute.
- */
- public String getDeclaringClass() {
- ConstPool cp = getConstPool();
- return cp.getClassName();
- }
-
- /**
- * Returns <code>max_stack</code>.
- */
- public int getMaxStack() {
- return maxStack;
- }
-
- /**
- * Sets <code>max_stack</code>.
- */
- public void setMaxStack(int value) {
- maxStack = value;
- }
-
- /**
- * Returns <code>max_locals</code>.
- */
- public int getMaxLocals() {
- return maxLocals;
- }
-
- /**
- * Sets <code>max_locals</code>.
- */
- public void setMaxLocals(int value) {
- maxLocals = value;
- }
-
- /**
- * Returns <code>code_length</code>.
- */
- public int getCodeLength() {
- return info.length;
- }
-
- /**
- * Returns <code>code[]</code>.
- */
- public byte[] getCode() {
- return info;
- }
-
- /**
- * Sets <code>code[]</code>.
- */
- void setCode(byte[] newinfo) { super.set(newinfo); }
-
- /**
- * Makes a new iterator for reading this code attribute.
- */
- public CodeIterator iterator() {
- return new CodeIterator(this);
- }
-
- /**
- * Returns <code>exception_table[]</code>.
- */
- public ExceptionTable getExceptionTable() { return exceptions; }
-
- /**
- * Returns <code>attributes[]</code>.
- * It returns a list of <code>AttributeInfo</code>.
- *
- * @see AttributeInfo
- */
- public List getAttributes() { return attributes; }
-
- /**
- * Returns the attribute with the specified name.
- * If it is not found, this method returns null.
- *
- * @param name attribute name
- * @return an <code>AttributeInfo</code> object or null.
- */
- public AttributeInfo getAttribute(String name) {
- return AttributeInfo.lookup(attributes, name);
- }
-
- /**
- * Copies code.
- */
- private byte[] copyCode(ConstPool destCp, Map classnames,
- ExceptionTable etable)
- throws BadBytecode
- {
- int len = getCodeLength();
- byte[] newCode = new byte[len];
-
- LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
- newCode, destCp, classnames);
- return LdcEntry.doit(newCode, ldc, etable);
- }
-
- private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
- ConstPool srcCp, byte[] newcode,
- ConstPool destCp, Map classnameMap)
- throws BadBytecode
- {
- int i2, index;
- LdcEntry ldcEntry = null;
-
- for (int i = beginPos; i < endPos; i = i2) {
- i2 = CodeIterator.nextOpcode(code, i);
- byte c = code[i];
- newcode[i] = c;
- switch (c & 0xff) {
- case LDC_W :
- case LDC2_W :
- case GETSTATIC :
- case PUTSTATIC :
- case GETFIELD :
- case PUTFIELD :
- case INVOKEVIRTUAL :
- case INVOKESPECIAL :
- case INVOKESTATIC :
- case NEW :
- case ANEWARRAY :
- case CHECKCAST :
- case INSTANCEOF :
- copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
- classnameMap);
- break;
- case LDC :
- index = code[i + 1] & 0xff;
- index = srcCp.copy(index, destCp, classnameMap);
- if (index < 0x100)
- newcode[i + 1] = (byte)index;
- else {
- LdcEntry ldc = new LdcEntry();
- ldc.where = i;
- ldc.index = index;
- ldc.next = ldcEntry;
- ldcEntry = ldc;
- }
- break;
- case INVOKEINTERFACE :
- copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
- classnameMap);
- newcode[i + 3] = code[i + 3];
- newcode[i + 4] = code[i + 4];
- break;
- case MULTIANEWARRAY :
- copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
- classnameMap);
- newcode[i + 3] = code[i + 3];
- break;
- default :
- while (++i < i2)
- newcode[i] = code[i];
-
- break;
- }
- }
-
- return ldcEntry;
- }
-
- private static void copyConstPoolInfo(int i, byte[] code, ConstPool srcCp,
- byte[] newcode, ConstPool destCp,
- Map classnameMap) {
- int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff);
- index = srcCp.copy(index, destCp, classnameMap);
- newcode[i] = (byte)(index >> 8);
- newcode[i + 1] = (byte)index;
- }
- }
-
- final class LdcEntry {
- LdcEntry next;
- int where;
- int index;
-
- static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable)
- throws BadBytecode
- {
- while (ldc != null) {
- int where = ldc.where;
- code = CodeIterator.insertGap(code, where, 1, false, etable);
- code[where] = (byte)Opcode.LDC_W;
- ByteArray.write16bit(ldc.index, code, where + 1);
- ldc = ldc.next;
- }
-
- return code;
- }
- }
|