diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2010-05-08 16:15:56 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2010-05-08 16:15:56 +0000 |
commit | 1b5a7c430821ff67ebe5014d7c9481dde3009c50 (patch) | |
tree | 3623bcc5e0278bfac719547dd56cbbf97463f0b3 /src | |
parent | eb36a2f1aa2dfeedea085f29ba1e1bb76a8da399 (diff) | |
download | javassist-1b5a7c430821ff67ebe5014d7c9481dde3009c50.tar.gz javassist-1b5a7c430821ff67ebe5014d7c9481dde3009c50.zip |
added a simple ASM-like API.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@542 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src')
-rw-r--r-- | src/main/javassist/bytecode/ByteStream.java | 193 | ||||
-rw-r--r-- | src/main/javassist/bytecode/ClassFileWriter.java | 730 | ||||
-rw-r--r-- | src/main/javassist/tools/Dump.java | 4 |
3 files changed, 925 insertions, 2 deletions
diff --git a/src/main/javassist/bytecode/ByteStream.java b/src/main/javassist/bytecode/ByteStream.java new file mode 100644 index 00000000..82b30c9c --- /dev/null +++ b/src/main/javassist/bytecode/ByteStream.java @@ -0,0 +1,193 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2010 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.OutputStream; +import java.io.IOException; + +final class ByteStream extends OutputStream { + private byte[] buf; + private int count; + + public ByteStream() { this(32); } + + public ByteStream(int size) { + buf = new byte[size]; + count = 0; + } + + public int getPos() { return count; } + public int size() { return count; } + + public void writeBlank(int len) { + enlarge(len); + count += len; + } + + public void write(byte[] data) { + write(data, 0, data.length); + } + + public void write(byte[] data, int off, int len) { + enlarge(len); + System.arraycopy(data, off, buf, count, len); + count += len; + } + + public void write(int b) { + enlarge(1); + int oldCount = count; + buf[oldCount] = (byte)b; + count = oldCount + 1; + } + + public void writeShort(int s) { + enlarge(2); + int oldCount = count; + buf[oldCount] = (byte)(s >>> 8); + buf[oldCount + 1] = (byte)s; + count = oldCount + 2; + } + + public void writeInt(int i) { + enlarge(4); + int oldCount = count; + buf[oldCount] = (byte)(i >>> 24); + buf[oldCount + 1] = (byte)(i >>> 16); + buf[oldCount + 2] = (byte)(i >>> 8); + buf[oldCount + 3] = (byte)i; + count = oldCount + 4; + } + + public void writeLong(long i) { + enlarge(8); + int oldCount = count; + buf[oldCount] = (byte)(i >>> 56); + buf[oldCount + 1] = (byte)(i >>> 48); + buf[oldCount + 2] = (byte)(i >>> 40); + buf[oldCount + 3] = (byte)(i >>> 32); + buf[oldCount + 4] = (byte)(i >>> 24); + buf[oldCount + 5] = (byte)(i >>> 16); + buf[oldCount + 6] = (byte)(i >>> 8); + buf[oldCount + 7] = (byte)i; + count = oldCount + 8; + } + + public void writeFloat(float v) { + writeInt(Float.floatToIntBits(v)); + } + + public void writeDouble(double v) { + writeLong(Double.doubleToLongBits(v)); + } + + public void writeUTF(String s) { + int sLen = s.length(); + int pos = count; + enlarge(sLen + 2); + + byte[] buffer = buf; + buffer[pos++] = (byte)(sLen >>> 8); + buffer[pos++] = (byte)sLen; + for (int i = 0; i < sLen; ++i) { + char c = s.charAt(i); + if (0x01 <= c && c <= 0x7f) + buffer[pos++] = (byte)c; + else { + writeUTF2(s, sLen, i); + return; + } + } + + count = pos; + } + + private void writeUTF2(String s, int sLen, int offset) { + int size = sLen; + for (int i = offset; i < sLen; i++) { + int c = s.charAt(i); + if (c > 0x7ff) + size += 2; // 3 bytes code + else if (c == 0 || c > 0x7f) + ++size; // 2 bytes code + } + + if (size > 65535) + throw new RuntimeException( + "encoded string too long: " + sLen + size + " bytes"); + + enlarge(size + 2); + int pos = count; + byte[] buffer = buf; + buffer[pos] = (byte)(size >>> 8); + buffer[pos + 1] = (byte)size; + pos += 2 + offset; + for (int j = offset; j < sLen; ++j) { + int c = s.charAt(j); + if (0x01 <= c && c <= 0x7f) + buffer[pos++] = (byte) c; + else if (c > 0x07ff) { + buffer[pos] = (byte)(0xe0 | ((c >> 12) & 0x0f)); + buffer[pos + 1] = (byte)(0x80 | ((c >> 6) & 0x3f)); + buffer[pos + 2] = (byte)(0x80 | (c & 0x3f)); + pos += 3; + } + else { + buffer[pos] = (byte)(0xc0 | ((c >> 6) & 0x1f)); + buffer[pos + 1] = (byte)(0x80 | (c & 0x3f)); + pos += 2; + } + } + + count = pos; + } + + public void write(int pos, int value) { + buf[pos] = (byte)value; + } + + public void writeShort(int pos, int value) { + buf[pos] = (byte)(value >>> 8); + buf[pos + 1] = (byte)value; + } + + public void writeInt(int pos, int value) { + buf[pos] = (byte)(value >>> 24); + buf[pos + 1] = (byte)(value >>> 16); + buf[pos + 2] = (byte)(value >>> 8); + buf[pos + 3] = (byte)value; + } + + public byte[] toByteArray() { + byte[] buf2 = new byte[count]; + System.arraycopy(buf, 0, buf2, 0, count); + return buf2; + } + + public void writeTo(OutputStream out) throws IOException { + out.write(buf, 0, count); + } + + public void enlarge(int delta) { + int newCount = count + delta; + if (newCount > buf.length) { + int newLen = buf.length << 1; + byte[] newBuf = new byte[newLen > newCount ? newLen : newCount]; + System.arraycopy(buf, 0, newBuf, 0, count); + buf = newBuf; + } + } +} diff --git a/src/main/javassist/bytecode/ClassFileWriter.java b/src/main/javassist/bytecode/ClassFileWriter.java new file mode 100644 index 00000000..012f495b --- /dev/null +++ b/src/main/javassist/bytecode/ClassFileWriter.java @@ -0,0 +1,730 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2010 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.OutputStream; +import java.io.DataOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * A quick class-file writer. This is useful when a generated + * class file is simple and the code generation should be fast. + * + * <p>Example: + * + * <blockquote><pre> + * ClassFileWriter cfw = new ClassFileWriter(ClassFile.JAVA_4, 0); + * ConstPoolWriter cpw = cfw.getConstPool(); + * + * FieldWriter fw = cfw.getFieldWriter(); + * fw.add(AccessFlag.PUBLIC, "value", "I", null); + * fw.add(AccessFlag.PUBLIC, "value2", "J", null); + * + * int thisClass = cpw.addClassInfo("sample/Test"); + * int superClass = cpw.addClassInfo("java/lang/Object"); + * + * MethodWriter mw = cfw.getMethodWriter(); + * + * mw.begin(AccessFlag.PUBLIC, MethodInfo.nameInit, "()V", null, null); + * mw.add(Opcode.ALOAD_0); + * mw.add(Opcode.INVOKESPECIAL); + * int signature = cpw.addNameAndTypeInfo(MethodInfo.nameInit, "()V"); + * mw.add16(cpw.addMethodrefInfo(superClass, signature)); + * mw.add(Opcode.RETURN); + * mw.codeEnd(1, 1); + * mw.end(null, null); + * + * mw.begin(AccessFlag.PUBLIC, "one", "()I", null, null); + * mw.add(Opcode.ICONST_1); + * mw.add(Opcode.IRETURN); + * mw.codeEnd(1, 1); + * mw.end(null, null); + * + * byte[] classfile = cfw.end(AccessFlag.PUBLIC, thisClass, superClass, + * null, null); + * </pre></blockquote> + * + * <p>The code above generates the following class: + * + * <blockquote><pre> + * package sample; + * public class Test { + * public int value; + * public long value2; + * public Test() { super(); } + * public one() { return 1; } + * } + * </pre></blockquote> + * + * @since 3.13 + */ +public class ClassFileWriter { + private ByteStream output; + private ConstPoolWriter constPool; + private FieldWriter fields; + private MethodWriter methods; + int thisClass, superClass; + + /** + * Constructs a class file writer. + * + * @param major the major version ({@link ClassFile#JAVA_4}, {@link ClassFile#JAVA_5}, ...). + * @param minor the minor version (0 for JDK 1.3 and later). + */ + public ClassFileWriter(int major, int minor) { + output = new ByteStream(512); + output.writeInt(0xCAFEBABE); // magic + output.writeShort(minor); + output.writeShort(major); + constPool = new ConstPoolWriter(output); + fields = new FieldWriter(constPool); + methods = new MethodWriter(constPool); + + } + + /** + * Returns a constant pool. + */ + public ConstPoolWriter getConstPool() { return constPool; } + + /** + * Returns a filed writer. + */ + public FieldWriter getFieldWriter() { return fields; } + + /** + * Returns a method writer. + */ + public MethodWriter getMethodWriter() { return methods; } + + /** + * Ends writing and returns the contents of the class file. + * + * @param accessFlags access flags. + * @param thisClass this class. an index indicating its <code>CONSTANT_Class_info</code>. + * @param superClass super class. an index indicating its <code>CONSTANT_Class_info</code>. + * @param interfaces implemented interfaces. + * index numbers indicating their <code>ClassInfo</code>. + * It may be null. + * @param aw attributes of the class file. May be null. + * + * @see AccessFlag + */ + public byte[] end(int accessFlags, int thisClass, int superClass, + int[] interfaces, AttributeWriter aw) { + constPool.end(); + output.writeShort(accessFlags); + output.writeShort(thisClass); + output.writeShort(superClass); + if (interfaces == null) + output.writeShort(0); + else { + int n = interfaces.length; + output.writeShort(n); + for (int i = 0; i < n; i++) + output.writeShort(interfaces[i]); + } + + output.enlarge(fields.dataSize() + methods.dataSize() + 6); + try { + output.writeShort(fields.size()); + fields.write(output); + + output.writeShort(methods.size()); + methods.write(output); + } + catch (IOException e) {} + + writeAttribute(output, aw, 0); + return output.toByteArray(); + } + + /** + * Ends writing and writes the contents of the class file into the + * given output stream. + * + * @param accessFlags access flags. + * @param thisClass this class. an index indicating its <code>CONSTANT_Class_info</code>. + * @param superClass super class. an index indicating its <code>CONSTANT_Class_info</code>. + * @param interfaces implemented interfaces. + * index numbers indicating their <code>CONSTATNT_Class_info</code>. + * It may be null. + * @param aw attributes of the class file. May be null. + * + * @see AccessFlag + */ + public void end(DataOutputStream out, + int accessFlags, int thisClass, int superClass, + int[] interfaces, AttributeWriter aw) + throws IOException + { + constPool.end(); + output.writeTo(out); + out.writeShort(accessFlags); + out.writeShort(thisClass); + out.writeShort(superClass); + if (interfaces == null) + out.writeShort(0); + else { + int n = interfaces.length; + out.writeShort(n); + for (int i = 0; i < n; i++) + out.writeShort(interfaces[i]); + } + + out.writeShort(fields.size()); + fields.write(out); + + out.writeShort(methods.size()); + methods.write(out); + if (aw == null) + out.writeShort(0); + else { + out.writeShort(aw.size()); + aw.write(out); + } + } + + /** + * This writes attributes. + * + * <p>For example, the following object writes a synthetic attribute: + * + * <pre> + * ConstPoolWriter cpw = ...; + * final int tag = cpw.addUtf8Info("Synthetic"); + * AttributeWriter aw = new AttributeWriter() { + * public int size() { + * return 1; + * } + * public void write(DataOutputStream out) throws java.io.IOException { + * out.writeShort(tag); + * out.writeInt(0); + * } + * }; + * </pre> + */ + public static interface AttributeWriter { + /** + * Returns the number of attributes that this writer will + * write. + */ + public int size(); + + /** + * Writes all the contents of the attributes. The binary representation + * of the contents is an array of <code>attribute_info</code>. + */ + public void write(DataOutputStream out) throws IOException; + } + + static void writeAttribute(ByteStream bs, AttributeWriter aw, int attrCount) { + if (aw == null) { + bs.writeShort(attrCount); + return; + } + + bs.writeShort(aw.size() + attrCount); + DataOutputStream dos = new DataOutputStream(bs); + try { + aw.write(dos); + dos.flush(); + } + catch (IOException e) {} + } + + /** + * Field. + */ + public static final class FieldWriter { + protected ByteStream output; + protected ConstPoolWriter constPool; + private int fieldCount; + + FieldWriter(ConstPoolWriter cp) { + output = new ByteStream(128); + constPool = cp; + fieldCount = 0; + } + + /** + * Adds a new field. + * + * @param accessFlags access flags. + * @param name the field name. + * @param descriptor the field type. + * @param aw the attributes of the field. may be null. + * @see AccessFlag + */ + public void add(int accessFlags, String name, String descriptor, AttributeWriter aw) { + int nameIndex = constPool.addUtf8Info(name); + int descIndex = constPool.addUtf8Info(descriptor); + add(accessFlags, nameIndex, descIndex, aw); + } + + /** + * Adds a new field. + * + * @param accessFlags access flags. + * @param name the field name. an index indicating its <code>CONSTANT_Utf8_info</code>. + * @param descriptor the field type. an index indicating its <code>CONSTANT_Utf8_info</code>. + * @param aw the attributes of the field. may be null. + * @see AccessFlag + */ + public void add(int accessFlags, int name, int descriptor, AttributeWriter aw) { + ++fieldCount; + output.writeShort(accessFlags); + output.writeShort(name); + output.writeShort(descriptor); + writeAttribute(output, aw, 0); + } + + int size() { return fieldCount; } + + int dataSize() { return output.size(); } + + /** + * Writes the added fields. + */ + void write(OutputStream out) throws IOException { + output.writeTo(out); + } + } + + /** + * Method. + */ + public static final class MethodWriter { + protected ByteStream output; + protected ConstPoolWriter constPool; + private int methodCount; + protected int codeIndex; + protected int throwsIndex; + protected int stackIndex; + + private int startPos; + private boolean isAbstract; + private int catchPos; + private int catchCount; + + MethodWriter(ConstPoolWriter cp) { + output = new ByteStream(256); + constPool = cp; + methodCount = 0; + codeIndex = 0; + throwsIndex = 0; + stackIndex = 0; + } + + /** + * Starts Adding a new method. + * + * @param accessFlags access flags. + * @param name the method name. + * @param descriptor the method signature. + * @param exceptions throws clause. It may be null. + * The class names must be the JVM-internal + * representations like <code>java/lang/Exception</code>. + * @param aw attributes to the <code>Method_info</code>. + */ + public void begin(int accessFlags, String name, String descriptor, + String[] exceptions, AttributeWriter aw) { + int nameIndex = constPool.addUtf8Info(name); + int descIndex = constPool.addUtf8Info(descriptor); + int[] intfs; + if (exceptions == null) + intfs = null; + else + intfs = constPool.addClassInfo(exceptions); + + begin(accessFlags, nameIndex, descIndex, intfs, aw); + } + + /** + * Starts adding a new method. + * + * @param accessFlags access flags. + * @param name the method name. an index indicating its <code>CONSTANT_Utf8_info</code>. + * @param descriptor the field type. an index indicating its <code>CONSTANT_Utf8_info</code>. + * @param exceptions throws clause. indexes indicating <code>CONSTANT_Class_info</code>s. + * It may be null. + * @param aw attributes to the <code>Method_info</code>. + */ + public void begin(int accessFlags, int name, int descriptor, int[] exceptions, AttributeWriter aw) { + ++methodCount; + output.writeShort(accessFlags); + output.writeShort(name); + output.writeShort(descriptor); + isAbstract = (accessFlags & AccessFlag.ABSTRACT) != 0; + + int attrCount = isAbstract ? 0 : 1; + if (exceptions != null) + ++attrCount; + + writeAttribute(output, aw, attrCount); + + if (exceptions != null) + writeThrows(exceptions); + + if (!isAbstract) { + if (codeIndex == 0) + codeIndex = constPool.addUtf8Info(CodeAttribute.tag); + + startPos = output.getPos(); + output.writeShort(codeIndex); + output.writeBlank(12); // attribute_length, maxStack, maxLocals, code_lenth + } + + catchPos = -1; + catchCount = 0; + } + + private void writeThrows(int[] exceptions) { + if (throwsIndex == 0) + throwsIndex = constPool.addUtf8Info(ExceptionsAttribute.tag); + + output.writeShort(throwsIndex); + output.writeInt(exceptions.length * 2 + 2); + output.writeShort(exceptions.length); + for (int i = 0; i < exceptions.length; i++) + output.writeShort(exceptions[i]); + } + + /** + * Appends an 8bit value of bytecode. + * + * @see Opcode + */ + public void add(int b) { + output.write(b); + } + + /** + * Appends a 16bit value of bytecode. + */ + public void add16(int b) { + output.writeShort(b); + } + + /** + * Appends a 32bit value of bytecode. + */ + public void add32(int b) { + output.writeInt(b); + } + + /** + * Appends a invokevirtual, inovkespecial, or invokestatic bytecode. + * + * @see Opcode + */ + public void addInvoke(int opcode, String targetClass, String methodName, + String descriptor) { + int target = constPool.addClassInfo(targetClass); + int nt = constPool.addNameAndTypeInfo(methodName, descriptor); + int method = constPool.addMethodrefInfo(target, nt); + add(opcode); + add16(method); + } + + /** + * Ends appending bytecode. + */ + public void codeEnd(int maxStack, int maxLocals) { + if (!isAbstract) { + output.writeShort(startPos + 6, maxStack); + output.writeShort(startPos + 8, maxLocals); + output.writeInt(startPos + 10, output.getPos() - startPos - 14); // code_length + catchPos = output.getPos(); + catchCount = 0; + output.writeShort(0); // number of catch clauses + } + } + + /** + * Appends an <code>exception_table</code> entry to the + * <code>Code_attribute</code>. This method is available + * only after the <code>codeEnd</code> method is called. + * + * @param catchType an index indicating a <code>CONSTANT_Class_info</code>. + */ + public void addCatch(int startPc, int endPc, int handlerPc, int catchType) { + ++catchCount; + output.writeShort(startPc); + output.writeShort(endPc); + output.writeShort(handlerPc); + output.writeShort(catchType); + } + + /** + * Ends adding a new method. The <code>add</code> method must be + * called before the <code>end</code> method is called. + * + * @param smap a stack map table. may be null. + * @param aw attributes to the <code>Code_attribute</code>. + * may be null. + */ + public void end(StackMapTable.Writer smap, AttributeWriter aw) { + if (isAbstract) + return; + + // exception_table_length + output.writeShort(catchPos, catchCount); + + int attrCount = smap == null ? 0 : 1; + writeAttribute(output, aw, attrCount); + + if (smap != null) { + if (stackIndex == 0) + stackIndex = constPool.addUtf8Info(StackMapTable.tag); + + output.writeShort(stackIndex); + byte[] data = smap.toByteArray(); + output.writeInt(data.length); + output.write(data); + } + + // Code attribute_length + output.writeInt(startPos + 2, output.getPos() - startPos - 6); + } + + int size() { return methodCount; } + + int dataSize() { return output.size(); } + + /** + * Writes the added methods. + */ + void write(OutputStream out) throws IOException { + output.writeTo(out); + } + } + + /** + * Constant Pool. + */ + public static final class ConstPoolWriter { + ByteStream output; + protected int startPos; + protected int num; + + ConstPoolWriter(ByteStream out) { + output = out; + startPos = out.getPos(); + num = 1; + output.writeShort(1); // number of entries + } + + /** + * Makes <code>CONSTANT_Class_info</code> objects for each class name. + * + * @return an array of indexes indicating <code>CONSTANT_Class_info</code>s. + */ + public int[] addClassInfo(String[] classNames) { + int n = classNames.length; + int[] result = new int[n]; + for (int i = 0; i < n; i++) + result[i] = addClassInfo(classNames[i]); + + return result; + } + + /** + * Adds a new <code>CONSTANT_Class_info</code> structure. + * + * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure + * for storing the class name. + * + * @param jvmname the JVM-internal representation of a class name. + * e.g. <code>java/lang/Object</code>. + * @return the index of the added entry. + */ + public int addClassInfo(String jvmname) { + int utf8 = addUtf8Info(jvmname); + output.write(ClassInfo.tag); + output.writeShort(utf8); + return num++; + } + + /** + * Adds a new <code>CONSTANT_Class_info</code> structure. + * + * @param name <code>name_index</code> + * @return the index of the added entry. + */ + public int addClassInfo(int name) { + output.write(ClassInfo.tag); + output.writeShort(name); + return num++; + } + + /** + * Adds a new <code>CONSTANT_NameAndType_info</code> structure. + * + * @param name <code>name_index</code> + * @param type <code>descriptor_index</code> + * @return the index of the added entry. + */ + public int addNameAndTypeInfo(String name, String type) { + return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type)); + } + + /** + * Adds a new <code>CONSTANT_NameAndType_info</code> structure. + * + * @param name <code>name_index</code> + * @param type <code>descriptor_index</code> + * @return the index of the added entry. + */ + public int addNameAndTypeInfo(int name, int type) { + output.write(NameAndTypeInfo.tag); + output.writeShort(name); + output.writeShort(type); + return num++; + } + + /** + * Adds a new <code>CONSTANT_Fieldref_info</code> structure. + * + * @param classInfo <code>class_index</code> + * @param nameAndTypeInfo <code>name_and_type_index</code>. + * @return the index of the added entry. + */ + public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) { + output.write(FieldrefInfo.tag); + output.writeShort(classInfo); + output.writeShort(nameAndTypeInfo); + return num++; + } + + /** + * Adds a new <code>CONSTANT_Methodref_info</code> structure. + * + * @param classInfo <code>class_index</code> + * @param nameAndTypeInfo <code>name_and_type_index</code>. + * @return the index of the added entry. + */ + public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) { + output.write(MethodrefInfo.tag); + output.writeShort(classInfo); + output.writeShort(nameAndTypeInfo); + return num++; + } + + /** + * Adds a new <code>CONSTANT_InterfaceMethodref_info</code> + * structure. + * + * @param classInfo <code>class_index</code> + * @param nameAndTypeInfo <code>name_and_type_index</code>. + * @return the index of the added entry. + */ + public int addInterfaceMethodrefInfo(int classInfo, + int nameAndTypeInfo) { + output.write(InterfaceMethodrefInfo.tag); + output.writeShort(classInfo); + output.writeShort(nameAndTypeInfo); + return num++; + } + + /** + * Adds a new <code>CONSTANT_String_info</code> + * structure. + * + * <p>This also adds a new <code>CONSTANT_Utf8_info</code> + * structure. + * + * @return the index of the added entry. + */ + public int addStringInfo(String str) { + output.write(StringInfo.tag); + output.writeShort(addUtf8Info(str)); + return num++; + } + + /** + * Adds a new <code>CONSTANT_Integer_info</code> + * structure. + * + * @return the index of the added entry. + */ + public int addIntegerInfo(int i) { + output.write(IntegerInfo.tag); + output.writeInt(i); + return num++; + } + + /** + * Adds a new <code>CONSTANT_Float_info</code> + * structure. + * + * @return the index of the added entry. + */ + public int addFloatInfo(float f) { + output.write(FloatInfo.tag); + output.writeFloat(f); + return num++; + } + + /** + * Adds a new <code>CONSTANT_Long_info</code> + * structure. + * + * @return the index of the added entry. + */ + public int addLongInfo(long l) { + output.write(LongInfo.tag); + output.writeLong(l); + int n = num; + num += 2; + return n; + } + + /** + * Adds a new <code>CONSTANT_Double_info</code> + * structure. + * + * @return the index of the added entry. + */ + public int addDoubleInfo(double d) { + output.write(DoubleInfo.tag); + output.writeDouble(d); + int n = num; + num += 2; + return n; + } + + /** + * Adds a new <code>CONSTANT_Utf8_info</code> + * structure. + * + * @return the index of the added entry. + */ + public int addUtf8Info(String utf8) { + output.write(Utf8Info.tag); + output.writeUTF(utf8); + return num++; + } + + /** + * Writes the contents of this class pool. + */ + void end() { + output.writeShort(startPos, num); + } + } +} diff --git a/src/main/javassist/tools/Dump.java b/src/main/javassist/tools/Dump.java index 149cc902..2f064a8b 100644 --- a/src/main/javassist/tools/Dump.java +++ b/src/main/javassist/tools/Dump.java @@ -17,7 +17,7 @@ package javassist.tools; import java.io.*; import javassist.bytecode.ClassFile; -import javassist.bytecode.ClassFileWriter; +import javassist.bytecode.ClassFilePrinter; /** * Dump is a tool for viewing the class definition in the given @@ -52,6 +52,6 @@ public class Dump { w.getConstPool().print(out); out.println(); out.println("*** members ***"); - ClassFileWriter.print(w, out); + ClassFilePrinter.print(w, out); } } |