Initial commit from SVN.

This commit is contained in:
wcrisman
2014-05-30 10:31:51 -07:00
commit b45e56b890
1968 changed files with 370949 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="/Common"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Class File Services</name>
<comment></comment>
<projects>
<project>Common</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,123 @@
package com.de22.javabytecode;
import com.de22.javabytecode.attribute.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Defines an attribute in any of the attribute collections.
* See the JVM specification 4.7.
* Subclasses of this type will provided additional functionality.
*/
public abstract class CodeAttribute extends Component {
/** The index of the attribute's name in the constant collection. */
private short nameIndex = -1;
/**
* CodeAttribute constructor.
*/
public CodeAttribute(Type type) {
super(type);
}//CodeAttribute()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public abstract String getDefaultName();
/**
* Gets the index of the attribute's name in the type's constant pool.
* @return The index of the attribute name.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public abstract int getSize();
/**
* Reads an attribute from the given stream.
* @param type The type object that the attribute will belong to.
* @param in The input stream to read the attribute from.
*/
protected static CodeAttribute readAttribute(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
CodeAttribute attribute = null;
short nameIndex = in.readShort();
Constant constant = type.getConstant(nameIndex);
ConstantUtf8 constantUtf8 = constant instanceof ConstantUtf8 ? (ConstantUtf8) constant : constant instanceof ConstantString ? (ConstantUtf8) type.getConstant(((ConstantString) constant).getStringIndex()) : null;
//This should never occur, but seems to for some compiled java code (probably due to a bad compiler). We will simply replace the missing string with an empty string.//
if(constantUtf8 == null) {
// System.out.println("Null constant found (index = " + nameIndex + ") while reading an unidentified attribute.");
attribute = new Unidentified(type, "");
attribute.nameIndex = nameIndex;
attribute.readExternal(in);
}//if//
else {
String name = constantUtf8.getValue();
if(name.equalsIgnoreCase("SourceFile")) {
attribute = new SourceFile(type);
}//if//
else if(name.equalsIgnoreCase("Code")) {
attribute = new Code(type);
}//else if//
else if(name.equalsIgnoreCase("Exceptions")) {
attribute = new ExceptionIndexes(type);
}//else if//
else if(name.equalsIgnoreCase("LineNumberTable")) {
attribute = new LineNumberTable(type);
}//else if//
else if(name.equalsIgnoreCase("LocalVariableTable")) {
attribute = new LocalVariableTable(type);
}//else if//
else if(name.equalsIgnoreCase("InnerClasses")) {
attribute = new InnerClasses(type);
}//else if//
else if(name.equalsIgnoreCase("ConstantValue")) {
attribute = new ConstantValue(type);
}//else if//
else if(name.equalsIgnoreCase("Synthetic")) {
attribute = new Synthetic(type);
}//else if//
else {
attribute = new Unidentified(type, name);
}//else//
attribute.nameIndex = nameIndex;
attribute.readExternal(in);
}//else//
return attribute;
}//readAttribute()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
if(this.nameIndex == -1) {
//There is usually no need to read the name index since it is read in the readAttribute(Type, ObjectInput) method.//
nameIndex = in.readShort();
}//if//
//Note: We leave it to the attribute to read the length of the attribute because some will require this info and most will ignore it.//
}//readExternal()//
/**
* Sets the index of the attribute's name in the type's constant pool.
* @param nameIndex The index of the attribute name.
*/
public void setNameIndex(short nameIndex) {
this.nameIndex = nameIndex;
}//setNameIndex()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short nameIndex = getType().getConstantIndex(new ConstantUtf8(getType(), getDefaultName()));
//Write the constant index referenceing the attribute name.//
out.writeShort(nameIndex);
//Write size in bytes of the attribute.//
out.writeInt(getSize());
}//writeExternal()//
}//CodeAttribute//

View File

@@ -0,0 +1,122 @@
package com.de22.javabytecode;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public abstract class Component implements ITypeComponent {
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private Type type = null;
/**
* Converts a class name in the java class file format to class name in the java source format.
* @param type The class to convert to a java format (which except for native non-array types (such as int), can be sent to a class loader).
* @return The java source formatted class name.
*/
public static String classFileFormatToJavaFormat(String type) {
String result = null;
if(type.charAt(0) == '[') {
result = type.replace('/', '.');
}//if//
else if(type.charAt(0) == 'L') {
result = type.substring(1, type.length() - 1).replace('/', '.');
}//else if//
else {
switch(type.charAt(0)) {
case 'V': {
result = Void.TYPE.getName();
break;
}//case//
case 'I': {
result = Integer.TYPE.getName();
break;
}//case//
case 'B': {
result = Byte.TYPE.getName();
break;
}//case//
case 'C': {
result = Character.TYPE.getName();
break;
}//case//
case 'S': {
result = Short.TYPE.getName();
break;
}//case//
case 'Z': {
result = Boolean.TYPE.getName();
break;
}//case//
case 'D': {
result = Double.TYPE.getName();
break;
}//case//
case 'F': {
result = Float.TYPE.getName();
break;
}//case//
case 'J': {
result = Long.TYPE.getName();
break;
}//case//
}//switch//
}//else//
return result;
}//classFileFormatToJavaFormat()//
/**
* Converts class names in the java class file format to class names in the java source format.
* @param types The classes to convert to a java format.
* @return The java source formatted class names.
*/
public static String[] classFileFormatToJavaFormat(String[] types) {
String[] result = new String[types.length];
for(int typeIndex = 0; typeIndex < types.length; typeIndex++) {
result[typeIndex] = classFileFormatToJavaFormat(types[typeIndex]);
}//for//
return result;
}//classFileFormatToJavaFormat()//
/**
* Component constructor.
*/
public Component(Type type) {
super();
this.type = type;
}//Component()//
/**
* Appends a the end of line characters to the buffer.
* <p>This is a utility method to assist the toString(StringBuffer, int) implementations.
* @param buffer The buffer to write an end of line to.
*/
protected static void appendEndOfLine(StringBuffer buffer) {
buffer.append('\r');
buffer.append('\n');
}//appendEndOfLine()//
/**
* Appends tab characters to the buffer.
* <p>This is a utility method to assist the toString(StringBuffer, int) implementations.
* @param buffer The buffer to write a tabs to.
* @param tabCount The number of tabs to append.
*/
protected static void appendTabs(StringBuffer buffer, int tabCount) {
while(tabCount-- != 0) {
buffer.append('\t');
}//while//
}//appendTabs()//
/**
* Gets the class associated with this component.
* @return The class information that this component is a member of.
*/
protected Type getType() {
return type;
}//getType()//
/**
* Displays the component and all subcomponents in human readable string form.
* @param buffer The buffer to display to.
* @param tabCount The number of tabs to prepend to each line.
*/
public abstract void toString(StringBuffer buffer, int tabCount);
}//Component//

View File

@@ -0,0 +1,111 @@
package com.de22.javabytecode;
import java.io.IOException;
import com.common.debug.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public abstract class Constant extends Component {
public static final byte CONSTANT_UTF8 = 0x01;
public static final byte CONSTANT_INTEGER = 0x03;
public static final byte CONSTANT_FLOAT = 0x04;
public static final byte CONSTANT_LONG = 0x05;
public static final byte CONSTANT_DOUBLE = 0x06;
public static final byte CONSTANT_CLASS = 0x07;
public static final byte CONSTANT_STRING = 0x08;
public static final byte CONSTANT_FIELD_REF = 0x09;
public static final byte CONSTANT_METHOD_REF = 0x0A;
public static final byte CONSTANT_INTERFACE_METHOD_REF = 0x0B;
public static final byte CONSTANT_NAME_AND_TYPE = 0x0C;
/**
* Constant constructor.
*/
public Constant(Type type) {
super(type);
}//Constant()//
/**
* Gets this constant's identifying constant.
* @return The constant value that identifies this constant object type.
*/
public abstract byte getTag();
/**
* Gets a display string that shows the resulting value of the constant in a viewer friendly way.
* @return The viewer friendly constant result.
*/
public abstract String getPrettyValue();
/**
* Determines whether the constant takes double the constant entries in the class bytes.
* @return Whether the constant is a double size constant.
*/
public boolean isDoubleSize() {
return false;
}//isDoubleSize()//
/**
* Reads a constant from the given stream.
* @param type The type object that the constant will belong to.
* @param in The input stream to read the constant from.
*/
protected static Constant readConstant(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Constant constant = null;
short tag = in.readByte();
switch(tag) {
case CONSTANT_CLASS:
constant = new ConstantType(type);
break;
case CONSTANT_DOUBLE:
constant = new ConstantDouble(type);
break;
case CONSTANT_FIELD_REF:
constant = new ConstantFieldRef(type);
break;
case CONSTANT_FLOAT:
constant = new ConstantFloat(type);
break;
case CONSTANT_INTEGER:
constant = new ConstantInteger(type);
break;
case CONSTANT_INTERFACE_METHOD_REF:
constant = new ConstantInterfaceMethodRef(type);
break;
case CONSTANT_LONG:
constant = new ConstantLong(type);
break;
case CONSTANT_METHOD_REF:
constant = new ConstantMethodRef(type);
break;
case CONSTANT_NAME_AND_TYPE:
constant = new ConstantNameAndType(type);
break;
case CONSTANT_STRING:
constant = new ConstantString(type);
break;
case CONSTANT_UTF8:
constant = new ConstantUtf8(type);
break;
default:
Debug.halt();
break;
}//switch//
constant.readExternal(in);
return constant;
}//readConstant()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
//The tag will be read by the readConstant(Type, ObjectInput) method.//
}//readExternal()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
out.writeByte(getTag());
}//writeExternal()//
}//Constant//

View File

@@ -0,0 +1,223 @@
package com.de22.javabytecode;
import java.io.IOException;
import com.common.util.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Field extends Component {
private short accessFlags = 0; //The visibility of the field and the field modifiers.//
private short fieldNameIndex = 0; //The index in the constant collection of the name of this field.//
private short descriptorIndex = 0; //The index in the constant collection of the descriptor for this field.//
private IList attributes = new LiteList(10, 30); //The attributes associated with this field.//
/**
* Field constructor.
*/
protected Field(Type type) {
super(type);
}//Field()//
/**
* Field constructor.
*/
public Field(Type type, short accessFlags, short descriptorIndex, short fieldNameIndex) {
super(type);
this.accessFlags = accessFlags;
this.descriptorIndex = descriptorIndex;
this.fieldNameIndex = fieldNameIndex;
}//Field()//
/**
* Adds an attribute to the method.
* An attribute describes some property of the method.
* @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool.
* @return The index of the attribute in the attribute pool.
*/
public short addAttribute(CodeAttribute attribute) {
short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false);
attribute.setNameIndex(nameIndex);
attributes.add(attribute);
return (short) (attributes.getSize() - 1);
}//addAttribute()//
/**
* Removes the attribute referenced by the index.
* @param index The zero based index of the attribute to remove.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute removeAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.remove(constant);
}//getAttribute()//
/**
* Gets the attributes referenced by the index.
* @param index The zero based index of the attribute to retrieve.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute getAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.get(constant);
}//getAttribute()//
/**
* Gets the count of attributes associated with the type.
* @return The number of attributes for this type.
*/
public int getAttributeCount() {
return attributes.getSize();
}//getAttributeCount()//
/**
* Gets the field's access flags.
* @return The field's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_VOLITILE
* @see #ACC_FINAL
* @see #ACC_TRANSIENT
*/
public short getAccessFlags() {
return accessFlags;
}//getAccessFlags()//
/**
* Gets the index of constant in the classes constant pool for the field descriptor.
* @return The field descriptor's constant pool index.
*/
public short getDescriptorIndex() {
return descriptorIndex;
}//getDescriptorIndex()//
/**
* Gets the constant pool index identifying the field name.
* @return The field name's index in the constant pool.
*/
public short getFieldNameIndex() {
return fieldNameIndex;
}//getFieldNameIndex()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
short count = 0;
accessFlags = in.readShort();
fieldNameIndex = in.readShort();
descriptorIndex = in.readShort();
count = in.readShort();
while(count-- != 0) {
addAttribute(CodeAttribute.readAttribute(getType(), in));
}//while//
}//readExternal()//
/**
* Reads a field from the given stream.
* @param type The type object that the field will belong to.
* @param in The input stream to read the field from.
*/
protected static Field readField(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Field field = new Field(type);
field.readExternal(in);
return field;
}//readField()//
/**
* Sets the field's access flags.
* @param accessFlags The field's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_VOLITILE
* @see #ACC_FINAL
* @see #ACC_TRANSIENT
*/
public void setAccessFlags(short accessFlags) {
this.accessFlags = accessFlags;
}//setAccessFlags()//
/**
* Sets the index of constant in the classes constant pool for the field descriptor.
* @param descriptorIndex The field descriptor's constant pool index.
*/
public void setDescriptorIndex(short descriptorIndex) {
this.descriptorIndex = descriptorIndex;
}//setDescriptorIndex()//
/**
* Sets the constant pool index identifying the field name.
* @param nameIndex The field name's index in the constant pool.
*/
public void setFieldNameIndex(short fieldNameIndex) {
this.fieldNameIndex = fieldNameIndex;
}//setFieldNameIndex()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
appendTabs(buffer, tabCount);
buffer.append("Field (nameIndex=");
buffer.append(fieldNameIndex);
buffer.append(" descriptorIndex=");
buffer.append(descriptorIndex);
buffer.append(" accessFlags=");
buffer.append(accessFlags);
buffer.append(" descriptor='");
buffer.append(getType().getConstant(descriptorIndex));
buffer.append("' name='");
buffer.append(getType().getConstant(fieldNameIndex));
buffer.append("')");
if(attributes.getSize() > 0) {
buffer.append(' ');
buffer.append('{');
appendEndOfLine(buffer);
iterator = attributes.iterator();
while(iterator.hasNext()) {
CodeAttribute attribute = (CodeAttribute) iterator.next();
attribute.toString(buffer, tabCount + 1);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
}//if//
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
IIterator iterator = null;
out.writeShort(accessFlags);
out.writeShort(fieldNameIndex);
out.writeShort(descriptorIndex);
if(attributes != null) {
out.writeShort((short) attributes.getSize());
iterator = attributes.iterator();
while(iterator.hasNext()) {
((CodeAttribute) iterator.next()).writeExternal(out);
}//while//
}//if//
else {
out.writeShort((short) 0);
}//else//
}//writeExternal()//
}//Field//

View File

@@ -0,0 +1,26 @@
package com.de22.javabytecode;
import java.io.Externalizable;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public interface ITypeComponent extends Externalizable {
public static final short ACC_PUBLIC = 0x0001;
public static final short ACC_PRIVATE = 0x0002;
public static final short ACC_PROTECTED = 0x0004;
public static final short ACC_STATIC = 0x0008;
public static final short ACC_FINAL = 0x0010;
public static final short ACC_SUPER = 0x0020;
public static final short ACC_SYNCHRONIZED = 0x0020;
public static final short ACC_VOLITILE = 0x0040;
public static final short ACC_TRANSIENT = 0x0080;
public static final short ACC_NATIVE = 0x0100;
public static final short ACC_INTERFACE = 0x0200;
public static final short ACC_ABSTRACT = 0x0400;
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize();
}//ITypeComponent//

View File

@@ -0,0 +1,83 @@
package com.de22.javabytecode;
import java.io.IOException;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Interface extends Component {
private short interfaceIndex = 0; //The index in the constant table of the interface constant.//
/**
* Interface constructor.
*/
protected Interface(Type type) {
super(type);
}//Interface()//
/**
* Interface constructor.
*/
public Interface(Type type, short interfaceIndex) {
super(type);
this.interfaceIndex = interfaceIndex;
}//Interface()//
/**
* Gets the index of the interface class reference in the constant pool.
* @return The constant pool index of the interface class.
*/
public short getClassIndex() {
return interfaceIndex;
}//getClassIndex()//
/**
* Sets the index of the interface class reference in the constant pool.
* @param classIndex The constant pool index of the interface class.
*/
public void setClassIndex(short classIndex) {
this.interfaceIndex = classIndex;
}//setClassIndex()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
interfaceIndex = in.readShort();
}//readExternal()//
/**
* Reads a interface from the given stream.
* @param type The type object that the interface will belong to.
* @param in The input stream to read the interface from.
*/
protected static Interface readInterface(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Interface interfaze = new Interface(type);
interfaze.readExternal(in);
return interfaze;
}//readInterface()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Interface (interfaceIndex=");
buffer.append(interfaceIndex);
buffer.append(" name='");
buffer.append(getType().getConstant(interfaceIndex));
buffer.append("')");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
out.writeShort(interfaceIndex);
}//writeExternal()//
}//Interface//

View File

@@ -0,0 +1,264 @@
package com.de22.javabytecode;
import java.io.IOException;
import com.common.util.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Method extends Component {
private short accessFlags = 0; //The modifiers and visibility for the method.//
private short nameIndex = 0; //The index within the constant collection of the name constant for this method.//
private short descriptorIndex = 0; //The index within the constant collection of the descriptor for this method.//
private IList attributes = new LiteList(10, 30); //The attributes associated with this method.//
/**
* Gets the return type in class file format (ie: [I for int[] and Ljava.lang.Object; for java.lang.Object).
* @param descriptor The descriptor in class file format.
* @return The return type in class file format.
*/
public static String getReturnType(String descriptor) {
return descriptor.substring(descriptor.lastIndexOf(')') + 1);
}//getReturnType()//
/**
* Gets the method parameters in class file format (ie: [I for int[] and Ljava.lang.Object; for java.lang.Object).
* @param descriptor The descriptor in class file format.
* @return The collection of parameters in order and in class file format.
*/
public static String[] getParamterTypes(String descriptor) {
int descriptorIndex = 1;
int parameterIndex = 0;
String[] result = null;
int startIndex = 1;
//First count the parameters.//
while(descriptor.charAt(descriptorIndex) != ')') {
if(descriptor.charAt(descriptorIndex) == 'L') {
descriptorIndex = descriptor.indexOf(';', descriptorIndex);
parameterIndex++;
}//if//
else if(descriptor.charAt(descriptorIndex) != '[') {
parameterIndex++;
}//else if//
descriptorIndex++;
}//while//
result = new String[parameterIndex];
parameterIndex = 0;
descriptorIndex = 1;
//Next load the parameter class names.//
while(descriptor.charAt(descriptorIndex) != ')') {
if(descriptor.charAt(descriptorIndex) == 'L') {
descriptorIndex = descriptor.indexOf(';', descriptorIndex);
result[parameterIndex++] = descriptor.substring(startIndex, descriptorIndex + 1);
startIndex = descriptorIndex + 1;
}//if//
else if(descriptor.charAt(descriptorIndex) != '[') {
result[parameterIndex++] = descriptor.substring(startIndex, descriptorIndex + 1);
startIndex = descriptorIndex + 1;
}//else if//
descriptorIndex++;
}//while//
return result;
}//getParamterTypes()//
/**
* Method constructor.
*/
protected Method(Type type) {
super(type);
}//Method()//
/**
* Adds an attribute to the method.
* An attribute describes some property of the method.
* @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool.
* @return The index of the attribute in the attribute pool.
*/
public short addAttribute(CodeAttribute attribute) {
short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false);
attribute.setNameIndex(nameIndex);
attributes.add(attribute);
return (short) (attributes.getSize() - 1);
}//addAttribute()//
/**
* Gets the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the attribute to retrieve.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute getAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.get(constant);
}//getAttribute()//
/**
* Removes the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the attribute to remove.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute removeAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.remove(constant);
}//getAttribute()//
/**
* Gets the count of attributes associated with the type.
* @return The number of attributes for this type.
*/
public int getAttributeCount() {
return attributes.getSize();
}//getAttributeCount()//
/**
* Gets the method's access flags.
* @return The method's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_ABSTRACT
* @see #ACC_SYNCHRONIZED
* @see #ACC_NATIVE
* @see #ACC_FINAL
*/
public short getAccessFlags() {
return accessFlags;
}//getAccessFlags()//
/**
* Gets the index of constant in the classes constant pool for the method descriptor.
* @return The method descriptor's constant pool index.
*/
public short getDescriptorIndex() {
return descriptorIndex;
}//getDescriptorIndex()//
/**
* Gets the index of constant in the classes constant pool for the method name.
* @return The methods name's constant pool index.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
short length;
accessFlags = in.readShort();
nameIndex = in.readShort();
descriptorIndex = in.readShort();
length = in.readShort();
attributes = length > 0 ? new LiteList((int) length, 10) : LiteList.EMPTY_LIST;
while(length-- > 0) {
addAttribute(CodeAttribute.readAttribute(getType(), in));
}//while//
}//readExternal()//
/**
* Reads a method from the given stream.
* @param type The type object that the method will belong to.
* @param in The input stream to read the method from.
*/
protected static Method readMethod(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Method method = new Method(type);
method.readExternal(in);
return method;
}//readMethod()//
/**
* Sets the method's access flags.
* @param accessFlags The method's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_ABSTRACT
* @see #ACC_SYNCHRONIZED
* @see #ACC_NATIVE
* @see #ACC_FINAL
*/
public void setAccessFlags(short accessFlags) {
this.accessFlags = accessFlags;
}//setAccessFlags()//
/**
* Sets the index of constant in the classes constant pool for the method descriptor.
* @param descriptorIndex The method descriptor's constant pool index.
*/
public void setDescriptorIndex(short descriptorIndex) {
this.descriptorIndex = descriptorIndex;
}//setDescriptorIndex()//
/**
* Sets the index of constant in the classes constant pool for the method name.
* @param nameIndex The methods name's constant pool index.
*/
public void setNameIndex(short nameIndex) {
this.nameIndex = nameIndex;
}//setNameIndex()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
appendTabs(buffer, tabCount);
buffer.append("Method (accessFlags=");
buffer.append(accessFlags);
buffer.append(" nameIndex=");
buffer.append(nameIndex);
buffer.append(" descriptorIndex=");
buffer.append(descriptorIndex);
buffer.append(" Name='");
buffer.append(getType().getConstant(nameIndex));
buffer.append("' Signature='");
buffer.append(getType().getConstant(descriptorIndex));
buffer.append("')");
if(attributes.getSize() > 0) {
buffer.append(' ');
buffer.append('{');
appendEndOfLine(buffer);
iterator = attributes.iterator();
while(iterator.hasNext()) {
CodeAttribute attribute = (CodeAttribute) iterator.next();
attribute.toString(buffer, tabCount + 1);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
}//if//
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
short length = (short) (attributes != null ? attributes.getSize() : 0);
out.writeShort(accessFlags);
out.writeShort(nameIndex);
out.writeShort(descriptorIndex);
out.writeShort(length);
for(int index = 0; index < length; index++) {
((CodeAttribute) attributes.get(index)).writeExternal(out);
}//for//
}//writeExternal()//
}//Method//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
package com.de22.javabytecode.attribute;
import com.common.io.StreamSupport;
import com.common.util.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.constant.ConstantUtf8;
/**
* Copyright Declarative Engineering LLC 1999,2006<p>
*/
public class Code extends CodeAttribute {
private short maxStack = 0;
private short maxLocals = 0;
private byte[] code = null;
private IList exceptions = null;
private IList attributes = null;
public static final String DEFAULT_NAME = "Code";
/**
* Copyright Declarative Engineering LLC 1999<p>
*/
public static class CodeException {
public short startPc = 0;
public short endPc = 0;
public short handlerPc = 0;
/** A reference into the constant pool to a ClassConstant. */
public short catchType = 0;
public CodeException() {
}//CodeException()//
public CodeException(short startPc, short endPc, short handlerPc, short catchType) {
this.startPc = startPc;
this.endPc = endPc;
this.handlerPc = handlerPc;
this.catchType = catchType;
}//CodeException()//
}//CodeException//
/**
* Code constructor.
* @param type The class this constant is a member of.
*/
public Code(Type type) {
super(type);
}//Code()//
/**
* Code constructor.
* @param type The class this constant is a member of.
*/
public Code(Type type, byte[] codeBytes, short maxStack, short maxLocals) {
super(type);
this.maxLocals = maxLocals;
this.maxStack = maxStack;
this.code = codeBytes;
}//Code()//
/**
* Gets the number of defined exception handlers.
* @return The count of exception handler metadata for the code.
*/
public int getExceptionCount() {
return exceptions == null ? 0 : exceptions.getSize();
}//getExceptionCount()//
/**
* Gets the exception metadata at the given zero based index.
* @param index The zero based index of the exception to be retrieved.
* @return The code exception metadata.
*/
public CodeException getException(int index) {
return (CodeException) exceptions.get(index);
}//getException()//
/**
* Adds an attribute to the method.
* An attribute describes some property of the method.
* @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool.
* @return The index of the attribute in the attribute pool.
*/
public short addAttribute(CodeAttribute attribute) {
short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false);
attribute.setNameIndex(nameIndex);
attributes.add(attribute);
return (short) (attributes.getSize() - 1);
}//addAttribute()//
/**
* Gets the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the field to retrieve.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute getAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.get(constant);
}//getAttribute()//
/**
* Removes the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the field to remove.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute removeAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.remove(constant);
}//getAttribute()//
/**
* Gets the count of attributes associated with the type.
* @return The number of attributes for this type.
*/
public int getAttributeCount() {
return attributes == null ? 0 : attributes.getSize();
}//getAttributeCount()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
int length = 12 + (code != null ? code.length : 0) + (exceptions != null ? exceptions.getSize() * 8 : 0);
if(attributes != null) {
for(int index = 0; index < attributes.getSize(); index++) {
CodeAttribute next = (CodeAttribute) attributes.get(index);
length += next.getSize() + 6; //Add 6 because each attribute is preceeded by a 2b name index, and a 4b total length which are not included in the size reported by the attribute.//
}//while//
}//if//
return length;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int exceptionCount;
int attributeCount;
super.readExternal(in);
int size = in.readInt(); //Read the size of the attribute (totalLength).//
maxStack = in.readShort();
maxLocals = in.readShort();
code = new byte[in.readInt()];
if(StreamSupport.readBytes(in, code) != code.length) {
new RuntimeException("Error: Bad code size.");
}//if//
//in.read(code);
exceptionCount = in.readShort();
if(exceptionCount != 0) {
exceptions = new LiteList(exceptionCount, 10);
//while(exceptionCount-- != 0) {
for(int index = 0; index < exceptionCount; index++) {
exceptions.add(new CodeException(in.readShort(), in.readShort(), in.readShort(), in.readShort()));
}//while//
}//if//
attributeCount = in.readShort();
if(attributeCount > 0) {
attributes = new LiteList(attributeCount, 10);
//while(attributeCount-- != 0) {
for(int index = 0; index < attributeCount; index++) {
attributes.add(CodeAttribute.readAttribute(getType(), in));
}//while//
}//if//
//Test the getSize() method.//
if(size != getSize()) {
new RuntimeException("Error: Bad size: " + getSize()).printStackTrace();
}//if//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
appendTabs(buffer, tabCount);
buffer.append("Code CodeAttribute (MaxStack=");
buffer.append(maxStack);
buffer.append(" MaxLocals=");
buffer.append(maxLocals);
buffer.append(')');
buffer.append(' ');
buffer.append('{');
appendEndOfLine(buffer);
if(attributes != null) {
iterator = attributes.iterator();
while(iterator.hasNext()) {
CodeAttribute attribute = (CodeAttribute) iterator.next();
attribute.toString(buffer, tabCount + 1);
}//while//
}//if//
if(exceptions != null) {
iterator = exceptions.iterator();
while(iterator.hasNext()) {
CodeException exception = (CodeException) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("Exception (startPc=");
buffer.append(exception.startPc);
buffer.append(" endPc=");
buffer.append(exception.endPc);
buffer.append(" handlerPc=");
buffer.append(exception.handlerPc);
buffer.append(" catchType=");
buffer.append(exception.catchType);
buffer.append(')');
appendEndOfLine(buffer);
}//while//
}//if//
if(code != null) {
appendTabs(buffer, tabCount);
buffer.append("Code\t[");
appendEndOfLine(buffer);
buffer.append(com.de22.javabytecode.code.FormatSupport.formatCode(getType(), code, tabCount + 1));
appendTabs(buffer, tabCount + 1);
buffer.append("]");
appendEndOfLine(buffer);
}//if//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
int exceptionsLength = exceptions != null ? exceptions.getSize() : 0;
int attributesLength = attributes != null ? attributes.getSize() : 0;
super.writeExternal(out);
out.writeShort(maxStack);
out.writeShort(maxLocals);
out.writeInt(code.length);
out.write(code);
out.writeShort((short) exceptionsLength);
for(int index = 0; index < exceptionsLength; index++) {
CodeException codeException = (CodeException) exceptions.get(index);
out.writeShort(codeException.startPc);
out.writeShort(codeException.endPc);
out.writeShort(codeException.handlerPc);
out.writeShort(codeException.catchType);
}//for//
out.writeShort((short) attributesLength);
for(int index = 0; index < attributesLength; index++) {
((CodeAttribute) attributes.get(index)).writeExternal(out);
}//for//
}//writeExternal()//
}//Code//

View File

@@ -0,0 +1,78 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Used by fields to represent a constant that the field will be initialized to.
*/
public class ConstantValue extends CodeAttribute {
private short constantIndex = 0;
public static final String DEFAULT_NAME = "ConstantValue";
/**
* ConstantValue constructor.
* @param type The class this constant is a member of.
*/
public ConstantValue(Type type) {
super(type);
}//ConstantValue()//
/**
* Gets the index of the constant being referenced.
* @return The constant referenced by this code attribue.
*/
public short getConstantIndex() {
return constantIndex;
}//getConstantIndex()//
/**
* Sets the index of the constant being referenced.
* @param constantIndex The constant referenced by this code attribue.
*/
public void setConstantIndex(short constantIndex) {
this.constantIndex = constantIndex;
}//setConstantIndex()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
constantIndex = in.readShort();
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Constant CodeAttribute (ConstantIndex=");
buffer.append(constantIndex);
buffer.append(" Value=[ ");
buffer.append(getType().getConstant(constantIndex));
buffer.append(" ])");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
out.writeShort(constantIndex);
}//writeExternal()//
}//ConstantValue//

View File

@@ -0,0 +1,92 @@
package com.de22.javabytecode.attribute;
import com.common.util.optimized.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Maintains the exceptions thrown by a method?
*/
public class ExceptionIndexes extends CodeAttribute {
private IntArray indexes = new IntArray(10, 40);
public static final String DEFAULT_NAME = "Exceptions";
/**
* ExceptionIndexes constructor.
* @param type The class this constant is a member of.
*/
public ExceptionIndexes(Type type) {
super(type);
}//ExceptionIndexes()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (indexes != null ? indexes.getSize() * 2 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
short indexCount = 0;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
indexCount = in.readShort();
while(indexCount-- != 0) {
indexes.add((int) in.readShort());
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIntIterator iterator = indexes.iterator();
appendTabs(buffer, tabCount);
buffer.append("Exception Indexes (");
while(iterator.hasNext()) {
int index = iterator.next();
buffer.append(index);
if(iterator.hasNext()) {
buffer.append(',');
buffer.append(' ');
}//if//
}//while//
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
if(indexes != null) {
int length = indexes.getSize();
out.writeShort((short) length);
for(int index = 0; index < length; index++) {
out.writeShort((short) indexes.get(index));
}//for//
}//if//
else {
out.writeShort((short) 0);
}//else//
}//writeExternal()//
}//ExceptionIndexes//

View File

@@ -0,0 +1,143 @@
package com.de22.javabytecode.attribute;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteList;
import com.de22.javabytecode.CodeAttribute;
import com.de22.javabytecode.Type;
/**
* Copyright Declarative Engineering LLC 2007<p>
*/
public class InnerClasses extends CodeAttribute {
public static final String DEFAULT_NAME = "InnerClasses";
private IList innerClasses = null;
/**
* Identifies a single line number.
*/
public static class InnerClass {
/** References the class constant in the constant pool for the inner class. */
public short innerClassInfo = 0;
/** References the class constant in the constant pool for the outer class. */
public short outerClassInfo = 0;
/** References the name of the inner class in the constant pool. */
public short innerNameIndex = 0;
/** The modifiers for the inner class. */
public short innerClassAccessFlags = 0;
public InnerClass() {
}//InnerClass()//
public InnerClass(short innerClassInfo, short outerClassInfo, short innerNameIndex, short innerClassAccessFlags) {
this.innerClassInfo = innerClassInfo;
this.outerClassInfo = outerClassInfo;
this.innerNameIndex = innerNameIndex;
this.innerClassAccessFlags = innerClassAccessFlags;
}//InnerClass()//
}//InnerClass//
/**
* InnerClasses constructor.
* @param type
*/
public InnerClasses(Type type) {
super(type);
}//InnerClasses()//
/**
* Gets the count of inner classes.
* @return The number of inner classes defined in this code attribute.
*/
public int getInnerClassesCount() {
return innerClasses.getSize();
}//getInnerClassesCount()//
/**
* Gets the inner class data at the given zero based index.
* @param index The zero based index of the inner class.
* @return The inner class data.
*/
public InnerClass getInnerClass(int index) {
return (InnerClass) innerClasses.get(index);
}//getInnerClass()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (innerClasses != null ? innerClasses.getSize() * 8 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int innerClassCount;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
innerClassCount = in.readShort();
innerClasses = new LiteList(innerClassCount == 0 ? 1 : innerClassCount, 10);
while(innerClassCount-- > 0) {
innerClasses.add(new InnerClass(in.readShort(), in.readShort(), in.readShort(), in.readShort()));
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
if(innerClasses != null) {
iterator = innerClasses.iterator();
appendTabs(buffer, tabCount);
buffer.append("InnerClasses {");
appendEndOfLine(buffer);
while(iterator.hasNext()) {
InnerClass innerClass = (InnerClass) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("LocalVariable (innerClassInfo=");
buffer.append(innerClass.innerClassInfo);
buffer.append(" outerClassInfo=");
buffer.append(innerClass.outerClassInfo);
buffer.append(" innerNameIndex=");
buffer.append(innerClass.innerNameIndex);
buffer.append(" innerClassAccessFlags=");
buffer.append(innerClass.innerClassAccessFlags);
buffer.append(")");
appendEndOfLine(buffer);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//if//
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short length = (short) (innerClasses != null ? innerClasses.getSize() : 0);
super.writeExternal(out);
out.writeShort(length);
for(int index = 0; index < length; index++) {
InnerClass innerClass = (InnerClass) innerClasses.get(index);
out.writeShort(innerClass.innerClassInfo);
out.writeShort(innerClass.outerClassInfo);
out.writeShort(innerClass.innerNameIndex);
out.writeShort(innerClass.innerClassAccessFlags);
}//for//
}//writeExternal()//
}//InnerClasses//

View File

@@ -0,0 +1,115 @@
package com.de22.javabytecode.attribute;
import com.common.util.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* References a constant in the constant pool?
*/
public class LineNumberTable extends CodeAttribute {
public static final String DEFAULT_NAME = "LineNumberTable";
private IList lineNumbers = null;
/**
* Identifies a single line number.
*/
private static class LineNumber {
public short startPc = 0;
public short lineNumber = 0;
public LineNumber() {
}//LineNumber()//
public LineNumber(short startPc, short lineNumber) {
this.startPc = startPc;
this.lineNumber = lineNumber;
}//LineNumber()//
}//LineNumber//
/**
* ConstantValue constructor.
* @param type The class this constant is a member of.
*/
public LineNumberTable(Type type) {
super(type);
}//ConstantValue()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (lineNumbers != null ? lineNumbers.getSize() * 4 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
short length = 0;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
length = in.readShort();
if(length > 0) {
lineNumbers = new LiteList(length, 10);
}//if//
while(length-- != 0) {
lineNumbers.add(new LineNumber(in.readShort(), in.readShort()));
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
if(lineNumbers != null) {
iterator = lineNumbers.iterator();
appendTabs(buffer, tabCount);
buffer.append("LineNumbers {");
appendEndOfLine(buffer);
while(iterator.hasNext()) {
LineNumber lineNumber = (LineNumber) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("LineNumber (startPc=");
buffer.append(lineNumber.startPc);
buffer.append(" lineNumber=");
buffer.append(lineNumber.lineNumber);
buffer.append(")");
appendEndOfLine(buffer);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//if//
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short length = (short) (lineNumbers != null ? lineNumbers.getSize() : 0);
super.writeExternal(out);
out.writeShort(length);
for(int index = 0; index < length; index++) {
LineNumber lineNumber = (LineNumber) lineNumbers.get(index);
out.writeShort(lineNumber.startPc);
out.writeShort(lineNumber.lineNumber);
}//for//
}//writeExternal()//
}//ConstantValue//

View File

@@ -0,0 +1,148 @@
package com.de22.javabytecode.attribute;
import com.common.util.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* References a constant in the constant pool?
*/
public class LocalVariableTable extends CodeAttribute {
private IList localVariables = null;
public static final String DEFAULT_NAME = "LocalVariableTable";
/**
* Identifies a single local variable.
*/
public static class LocalVariable {
public short startPc = 0;
public short variableLength = 0;
public short nameIndex = 0;
public short descriptorIndex = 0;
public short index = 0;
public LocalVariable() {
}//LocalVariable()//
public LocalVariable(short startPc, short variableLength, short nameIndex, short descriptorIndex, short index) {
this.startPc = startPc;
this.variableLength = variableLength;
this.nameIndex = nameIndex;
this.descriptorIndex = descriptorIndex;
this.index = index;
}//LocalVariable()//
}//LocalVariable//
/**
* ConstantValue constructor.
* @param type The class this constant is a member of.
*/
public LocalVariableTable(Type type) {
super(type);
}//ConstantValue()//
/**
* Gets the number of local variables in the table.
* @return The number of local variables.
*/
public int getLocalVariableCount() {
return localVariables != null ? localVariables.getSize() : 0;
}//getLocalVariableCount()//
/**
* Gets the desired local variable metadata.
* @param index The zero based index of the desired local variable.
* @return The local variable.
*/
public LocalVariable getLocalVariable(int index) {
return (LocalVariable) localVariables.get(index);
}//getLocalVariable()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (localVariables != null ? localVariables.getSize() * 10 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
short length = 0;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
length = in.readShort();
if(length > 0) {
localVariables = new LiteList(length, 10);
}//if//
while(length-- != 0) {
localVariables.add(new LocalVariable(in.readShort(), in.readShort(), in.readShort(), in.readShort(), in.readShort()));
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
if(localVariables != null) {
iterator = localVariables.iterator();
appendTabs(buffer, tabCount);
buffer.append("Local Variables {");
appendEndOfLine(buffer);
while(iterator.hasNext()) {
LocalVariable localVariable = (LocalVariable) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("LocalVariable (startPc=");
buffer.append(localVariable.startPc);
buffer.append(" variableLength=");
buffer.append(localVariable.variableLength);
buffer.append(" nameIndex=");
buffer.append(localVariable.nameIndex);
buffer.append(" descriptorIndex=");
buffer.append(localVariable.descriptorIndex);
buffer.append(" name='");
buffer.append(getType().getConstant(localVariable.nameIndex));
buffer.append("' type='");
buffer.append(getType().getConstant(localVariable.descriptorIndex));
buffer.append("' ?index?=");
buffer.append(localVariable.index);
buffer.append(")");
appendEndOfLine(buffer);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//if//
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short length = (short) (localVariables != null ? localVariables.getSize() : 0);
super.writeExternal(out);
out.writeShort(length);
for(int index = 0; index < length; index++) {
LocalVariable localVariable = (LocalVariable) localVariables.get(index);
out.writeShort(localVariable.startPc);
out.writeShort(localVariable.variableLength);
out.writeShort(localVariable.nameIndex);
out.writeShort(localVariable.descriptorIndex);
out.writeShort(localVariable.index);
}//for//
}//writeExternal()//
}//ConstantValue//

View File

@@ -0,0 +1,78 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to the source file name associated with the class file.
*/
public class SourceFile extends CodeAttribute {
private short sourceFileIndex = 0;
public static final String DEFAULT_NAME = "SourceFile";
/**
* SourceFile constructor.
* @param type The class this constant is a member of.
*/
public SourceFile(Type type) {
super(type);
}//SourceFile()//
/**
* Gets the index in the constant pool of the source file's name.
* @return The index to the source file name constant (UTF8) in the constant pool.
*/
public short getSourceFileIndex() {
return sourceFileIndex;
}//getSourceFileIndex()//
/**
* Sets the index in the constant pool of the source file's name.
* @param sourceFileIndex The index to the source file name constant (UTF8) in the constant pool.
*/
public void setSourceFileIndex(short sourceFileIndex) {
this.sourceFileIndex = sourceFileIndex;
}//setSourceFileIndex()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
sourceFileIndex = in.readShort();
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Source File Reference CodeAttribute (sourceFileIndex=");
buffer.append(sourceFileIndex);
buffer.append(" fileName='");
buffer.append(getType().getConstant(sourceFileIndex));
buffer.append("')");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
out.writeShort(sourceFileIndex);
}//writeExternal()//
}//SourceFile//

View File

@@ -0,0 +1,58 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.CodeAttribute;
import com.de22.javabytecode.Type;
/**
* Copyright Declarative Engineering LLC 2007<p>
*/
public class Synthetic extends CodeAttribute {
public static final String DEFAULT_NAME = "Synthetic";
/**
* Synthetic constructor.
* @param type The class this constant is a member of.
*/
public Synthetic(Type type) {
super(type);
}//Synthetic()//
/* (non-Javadoc)
* @see com.de22.javabytecode.CodeAttribute#getDefaultName()
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/* (non-Javadoc)
* @see com.de22.javabytecode.CodeAttribute#getSize()
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int length = -1;
super.readExternal(in);
//Should always be zero.//
length = in.readInt();
in.skip(length);
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Constant Synthetic");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
}//writeExternal()//
}//Synthetic//

View File

@@ -0,0 +1,83 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Unidentified extends CodeAttribute {
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private String attributeName = null;
/** The unidentified data. This may never be null. */
private byte[] data = EMPTY_BYTE_ARRAY;
/**
* Unidentified constructor.
* @param type The class this constant is a member of.
* @param attributeName The name of the unidentified attribute (normally the name would select a different class).
*/
public Unidentified(Type type, String attributeName) {
super(type);
this.attributeName = attributeName;
}//Unidentified()//
/**
* Gets the name of the unidentified attribute.
* @return The attribute's name which identifies what the attribute data means.
*/
public String getAttributeName() {
return attributeName;
}//getAttributeName()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return attributeName;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return data.length;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int length = -1;
int readCount = 0;
super.readExternal(in);
length = in.readInt(); //Read the size of the attribute.//
data = new byte[length]; //Create the data array.//
//Read the data.//
while(readCount != data.length) {
readCount += in.read(data, readCount, data.length - readCount);
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Unidentified CodeAttribute (name=");
buffer.append(attributeName);
buffer.append(" Size=");
buffer.append(data.length);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
out.write(data);
}//writeExternal()//
}//Unidentified//

View File

@@ -0,0 +1,646 @@
package com.de22.javabytecode.code;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.common.io.*;
import com.common.util.*;
import com.common.util.optimized.IntArray;
import com.common.debug.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.Type.TypeMetadata;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class FormatSupport {
private static final int LINE_SPACING = 12;
private static final int SHORT_LINE_DESCRIPTION_SPACING = 32;
private static final int LINE_DESCRIPTION_SPACING = 36;
private static final boolean DISPLAY_PARAMETER_BYTES = false;
private static final char FILE_SEPARATOR = System.getProperty("file.separator").charAt(0);
private static final char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* FormatSupport constructor.
*/
public FormatSupport() {
super();
}//FormatSupport()//
/**
* Appends the byte to the buffer as a hex string.
* @param value The byte value to append.
* @param buffer The string buffer append to.
*/
public static void appendByteAsHex(byte value, StringBuffer buffer) {
byte highBits = (byte) ((value >> 4) & 0x0F);
byte lowBits = (byte) (value & 0x0F);
buffer.append(hexCharacters[highBits]);
buffer.append(hexCharacters[lowBits]);
}//appendByteAsHex()//
/**
* Adds the specified number of tabs to the buffer.
* @param tabCount The number of tabs to append.
* @param buffer The string buffer to add the tabs to.
*/
public static void appendTabs(int tabCount, StringBuffer buffer) {
while(tabCount-- != 0) {
buffer.append('\t');
}//while//
}//appendTabs()//
/**
* Formats the hex codes of a class file so that they may be easily read by humans.
* @param type The type metadata used to access the constant pool.
* @param codes The array of all class bytes. If the byte codes are not properly formatted then this method may not be able to format everything and will return what was formatted.
* @param tabLevel How many tabs to add to the beginning of every line. Any non-negative value may be used.
* @return The formatted code as a simple string.
*/
public static String formatCode(Type type, byte[] codes, int tabLevel) {
StringBuffer buffer = new StringBuffer(10000);
IList opCodes = OpCode.getOpCodes();
try {
for(int index = 0; index < codes.length; index++) {
int code = codes[index] & 0xFF;
String indexString = Integer.toString(index);
OpCode opCode = (OpCode) opCodes.get(code);
if(codes[index] == -86) { //switch statement//
int startingNumber;
int endingNumber;
int jumpOffset;
appendTabs(tabLevel, buffer);
buffer.append(" line " + indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append("0x");
appendByteAsHex(codes[index], buffer);
buffer.append(' ');
buffer.append(opCode.toString());
buffer.append('\r');
buffer.append('\n');
//Spaces//
while((++index) % 4 != 0) {
formatLine(codes[index], index, "Spacing", tabLevel, buffer);
}//while//
jumpOffset = StreamSupport.readInt(codes, index); //The default jump offset.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Default Jump Offset = " + jumpOffset, tabLevel, buffer);
startingNumber = StreamSupport.readInt(codes, index); //The first number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Starting Value = " + startingNumber, tabLevel, buffer);
endingNumber = StreamSupport.readInt(codes, index); //The last number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Ending Value = " + endingNumber, tabLevel, buffer);
for(int entryIndex = startingNumber; entryIndex <= endingNumber; entryIndex++) {
jumpOffset = StreamSupport.readInt(codes, index); //The default jump offset.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Jump Offset #" + entryIndex + " = " + jumpOffset, tabLevel, buffer);
}//for//
index--;
}//if//
else if(codes[index] == -85) { //lookup switch statement//
int numberOfCases;
int caseValue;
int caseOffset;
int defaultCaseOffset;
appendTabs(tabLevel, buffer);
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append("0x");
appendByteAsHex(codes[index], buffer);
buffer.append(' ');
buffer.append(opCode.toString());
buffer.append('\r');
buffer.append('\n');
//Spaces//
while((++index) % 4 != 0) {
formatLine(codes[index], index, "Spacing", tabLevel, buffer);
}//while//
defaultCaseOffset = StreamSupport.readInt(codes, index); //The default jump offset.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Default Jump Offset = " + defaultCaseOffset, tabLevel, buffer);
numberOfCases = StreamSupport.readInt(codes, index); //The first number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Number of cases = " + numberOfCases, tabLevel, buffer);
for(int caseIndex = 0; caseIndex < numberOfCases; caseIndex++) {
caseValue = StreamSupport.readInt(codes, index); //The last number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Case" + caseIndex + " value = " + caseValue, tabLevel, buffer);
caseOffset = StreamSupport.readInt(codes, index); //The last number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Case" + caseIndex + " offset = " + caseOffset, tabLevel, buffer);
}//for//
index--;
}//else if//
else {
int lineDataCharacterCount;
appendTabs(tabLevel, buffer);
lineDataCharacterCount = buffer.length();
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
if(DISPLAY_PARAMETER_BYTES) {
buffer.append("0x");
appendByteAsHex(codes[index], buffer);
buffer.append(' ');
}//if//
buffer.append(opCode.getName());
lineDataCharacterCount = buffer.length() - lineDataCharacterCount + 1;
for(int t = lineDataCharacterCount; t < LINE_DESCRIPTION_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append(opCode.getDescription());
buffer.append('\r');
buffer.append('\n');
if(DISPLAY_PARAMETER_BYTES) {
for(int param = 0; param < opCode.getParameterByteDescriptions().getSize(); param++) {
indexString = new Integer(index + param + 1).toString();
code = (codes[index + param + 1] < 0 ? ((int) codes[index + param + 1]) + 256 : (int) codes[index + param + 1]);
appendTabs(tabLevel, buffer);
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append("0x");
appendByteAsHex(codes[index + param + 1], buffer);
buffer.append(" ");
buffer.append(opCode.getParameterByteDescriptions().get(param));
buffer.append('\r');
buffer.append('\n');
}//for//
}//if//
else {
int codeIndex = index + 1;
for(int param = 0; param < opCode.getParameterDescriptions().getSize(); param++) {
int paramType = opCode.getParameterTypes()[param];
long value = 0;
int paramByteCount;
int lineDisplayCharacterCount = 0;
boolean isConstantRef = false;
appendTabs(tabLevel, buffer);
lineDataCharacterCount = buffer.length();
switch(paramType) {
case OpCode.SHORT_CONSTANT_REF: {
value = (long) (codes[codeIndex] & 0xFF);
//if(((short) value) < 0) {
// buffer.append(type.getConstant((short) value));
//}
paramByteCount = 1;
isConstantRef = true;
break;
}//case//
case OpCode.CONSTANT_REF: {
value = (long) ((((codes[codeIndex] & 0xFF) << 8) | (codes[codeIndex + 1] & 0xFF)) & 0xFFFF);
//if(((short) value) < 0) {
// buffer.append(type.getConstant((short) value));
//}
paramByteCount = 2;
isConstantRef = true;
break;
}//case//
case OpCode.SIGNED_BYTE: {
value = (long) codes[codeIndex];
paramByteCount = 1;
break;
}//case//
case OpCode.UNSIGNED_BYTE: {
value = (long) (codes[codeIndex] & 0xFF);
paramByteCount = 1;
break;
}//case//
case OpCode.SIGNED_SHORT: {
value = (long) (((codes[codeIndex] & 0xFF) << 8) | (codes[codeIndex + 1] & 0xFF));
paramByteCount = 2;
break;
}//case//
case OpCode.UNSIGNED_SHORT: {
value = (long) ((((codes[codeIndex] & 0xFF) << 8) | (codes[codeIndex + 1] & 0xFF)) & 0xFFFF);
paramByteCount = 2;
break;
}//case//
case OpCode.SIGNED_INT: {
value = (long) (((codes[codeIndex] & 0xFF) << 24) | ((codes[codeIndex + 1] & 0xFF) << 16) | ((codes[codeIndex + 2] & 0xFF) << 8) | (codes[codeIndex + 3] & 0xFF));
paramByteCount = 4;
break;
}//case//
case OpCode.UNSIGNED_INT: {
value = (long) ((((codes[codeIndex] & 0xFF) << 24) | ((codes[codeIndex + 1] & 0xFF) << 16) | ((codes[codeIndex + 2] & 0xFF) << 8) | (codes[codeIndex + 3] & 0xFF)) & 0xFFFF);
paramByteCount = 4;
break;
}//case//
default:
throw new RuntimeException("Unexpected opcode parameter type.");
}//switch//
if(paramByteCount == 1) {
buffer.append(" line ");
lineDisplayCharacterCount = buffer.length();
buffer.append(codeIndex);
lineDisplayCharacterCount = buffer.length() - lineDisplayCharacterCount;
}//if//
else {
buffer.append(" lines ");
lineDisplayCharacterCount = buffer.length();
buffer.append(codeIndex);
buffer.append("-");
buffer.append(codeIndex + paramByteCount - 1);
lineDisplayCharacterCount = buffer.length() - lineDisplayCharacterCount + 1;
}//else//
for(int t = lineDisplayCharacterCount; t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append(value);
lineDataCharacterCount = buffer.length() - lineDataCharacterCount + 1;
if(isConstantRef) {
for(int t = lineDataCharacterCount; t < SHORT_LINE_DESCRIPTION_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append('{');
buffer.append(type.getConstant((short) value).getPrettyValue());
buffer.append('}');
buffer.append(' ');
}//if//
else {
for(int t = lineDataCharacterCount; t < LINE_DESCRIPTION_SPACING; t++) {buffer.append(' ');} //Space evenly//
}//else//
buffer.append(opCode.getParameterDescriptions().get(param));
buffer.append('\r');
buffer.append('\n');
codeIndex += paramByteCount;
}//for//
}//else//
index += opCode.getParameterByteDescriptions().getSize();
}//else//
}//for//
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
return buffer.toString();
}//formatCode()//
/**
* Will format a descriptor string using the parameters and return type of the method.
* This is used to create method descriptors for a class file.
* <p>Example: void methodName(double[] a, String b) -> ([DLjava/lang/String;)V;
* @param returnType The descriptor's return type.
* @param parameterTypes The descriptor's parameter types (in order of parameter).
* @param buffer The buffer to write the output to.
*/
public static void formatDescriptor(Class returnType, Class[] parameterTypes, StringBuffer buffer) {
buffer.append('(');
if(parameterTypes != null) {
for(int index = 0; index < parameterTypes.length; index++) {
formatType(parameterTypes[index], buffer);
}//for//
}//if//
buffer.append(')');
formatType(returnType, buffer);
}//formatDescriptor()//
/**
* Used to format a line when outputing the interperated class file's hex codes.
*/
public static void formatLine(byte code, int index, String message, int tabLevel, StringBuffer buffer) {
String indexString = new Integer(index).toString();
appendTabs(tabLevel, buffer);
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < 4; t++) {buffer.append(' ');} //Space evenly//
appendByteAsHex(code, buffer);
buffer.append(' ');
buffer.append(message);
buffer.append('\r');
buffer.append('\n');
}//formatLine()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type Class The non-primitive class to convert to a string.
* @param buffer The buffer to write the string to.
*/
public static void formatNonPrimitiveType(Class type, StringBuffer buffer) {
formatNonPrimitiveType(type.getName(), buffer);
}//formatNonPrimitiveType()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type The non-primitive class to convert to a string.
* @param buffer The buffer to write the string to.
*/
public static void formatNonPrimitiveType(String qualifiedTypeName, StringBuffer buffer) {
StringTokenizer tokenizer = new StringTokenizer(qualifiedTypeName, ".");
boolean isFirst = true;
while(tokenizer.hasMoreTokens()) {
if(!isFirst) {
buffer.append('/');
}//if//
else {
isFirst = false;
}//else//
buffer.append(tokenizer.nextToken());
}//while//
}//formatNonPrimitiveType()//
/**
* Formats a class to a class file compatible string.
* @param type The class to convert to a string.
* @param buffer The buffer to write the output to.
*/
public static void formatType(Class type, StringBuffer buffer) {
if(type != null) {
while(type.isArray()) {
buffer.append('[');
type = type.getComponentType();
}//while//
}//if//
if((type == null) || (type.equals(Void.TYPE))) {
buffer.append('V');
}//if//
else if(type.isPrimitive()) {
if(type.equals(Integer.TYPE)) {
buffer.append('I');
}//if//
else if(type.equals(Byte.TYPE)) {
buffer.append('B');
}//else if//
else if(type.equals(Character.TYPE)) {
buffer.append('C');
}//else if//
else if(type.equals(Short.TYPE)) {
buffer.append('S');
}//else if//
else if(type.equals(Boolean.TYPE)) {
buffer.append('Z');
}//else if//
else if(type.equals(Double.TYPE)) {
buffer.append('D');
}//else if//
else if(type.equals(Float.TYPE)) {
buffer.append('F');
}//else if//
else if(type.equals(Long.TYPE)) {
buffer.append('J');
}//else if//
}//else if//
else {
buffer.append('L');
formatNonPrimitiveType(type.getName(), buffer);
buffer.append(';');
}//else//
}//formatType()//
/**
* Reverse engineers a class file and prints the output to the console.
* @param args The array of initialization parameters.
* args[0] = The path and file name of the class or jar or path to a class file directory to reverse engineer.
* args[1] = The optional path (must exist) where the output will be stored. If the files exist they will be over written. If not specified the output will go to the console.
*/
public static void main(String[] args) {
String debugText = null;
long t = System.currentTimeMillis();
try {
File file = new File(args[0]);
File path = args.length > 1 ? new File(args[1]) : null;
if(path != null && (path.isFile() || (!path.exists() && !path.mkdirs()))) {
path = null;
}//if//
if(file.isDirectory()) {
LiteList directoryStack = new LiteList(10, 20);
LiteList listingStack = new LiteList(10, 20);
IntArray listingIndexStack = new IntArray(10, 20);
File directory = file;
File[] files = directory.listFiles();
for(int index = 0; index < files.length; index++) {
if(files[index].isDirectory()) {
File[] subfiles = files[index].listFiles();
if(subfiles.length > 0) {
directoryStack.add(directory);
listingStack.add(files);
listingIndexStack.add(index);
directory = files[index];
files = subfiles;
index = 0;
}//if//
}//if//
else if(files[index].getName().endsWith(".class")) {
debugText = files[index].getPath();
processClassFile(new FileInputStream(files[index]), path);
}//else if//
if((index == files.length - 1) && (directoryStack.getSize() > 0)) {
directory = (File) directoryStack.remove(directoryStack.getSize() - 1);
files = (File[]) listingStack.remove(listingStack.getSize() - 1);
index = listingIndexStack.remove(listingIndexStack.getSize() - 1);
}//if//
}//for//
}//if//
else if(file.getName().endsWith(".class")) {
debugText = file.getPath();
byte[] bytes = StreamSupport.readBytes(new FileInputStream(file));
processClassFile(new ByteArrayInputStream(bytes), path);
}//else if//
else if(file.getName().endsWith(".jar") || file.getName().endsWith(".zip")) {
ZipFile zip = null;
Enumeration enumeration = null;
if(file.getName().endsWith("jar")) {
zip = new JarFile(file, false, JarFile.OPEN_READ);
}//if//
else {
zip = new ZipFile(file, ZipFile.OPEN_READ);
}//else//
try {
enumeration = zip.entries();
while(enumeration.hasMoreElements()) {
ZipEntry entry = (ZipEntry) enumeration.nextElement();
if(!entry.isDirectory()) {
if(entry.getName().endsWith(".class")) {
InputStream in = zip.getInputStream(entry);
byte[] bytes = new byte[in.available()];
ByteArrayInputStream bin;
int readCount = 0;
debugText = entry.getName();
while(readCount < bytes.length) {
readCount += in.read(bytes, readCount, bytes.length - readCount);
}//while//
//Convert the zip input stream to a byte array stream.//
bin = new ByteArrayInputStream(bytes);
processClassFile(bin, path);
in.close();
}//if//
}//if//
}//while//
}//try//
finally {
zip.close();
}//finally//
}//else if//
}//try//
catch(Throwable e) {
Debug.log(e, "Caught while processing the class file: " + debugText);
}//catch//
Debug.log("Total time (milliseconds): " + (System.currentTimeMillis() - t));
System.exit(0);
}//main()//
/**
* Processes a class file and writes out the byte codes in a semi-readable form.
* @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method.
* @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise.
*/
private static void processClassFile(InputStream bytesIn, File outputPath) throws Throwable {
StringBuffer buffer = null;
ObjectInputStream in = null;
Type type = null;
try {
File outputFile = null;
TypeMetadata metadata = null;
in = new ObjectInputStream(bytesIn, null, null);
buffer = new StringBuffer(5000);
type = new Type();
type.readExternal(in);
type.toString(buffer, 0);
metadata = type.collectMetadata();
if(outputPath != null) {
String fileName = metadata.getTypeName().replace('.', FILE_SEPARATOR) + ".txt";
String directoryName = fileName.lastIndexOf(FILE_SEPARATOR) != -1 ? fileName.substring(0, fileName.lastIndexOf(FILE_SEPARATOR)) : "";
File outputDirectory = new File(outputPath, directoryName);
outputFile = new File(outputPath, fileName);
if(!outputDirectory.exists()) {
outputDirectory.mkdirs();
}//if//
if(!outputFile.exists()) {
outputFile.createNewFile();
}//if//
}//if//
if(outputFile == null) {
Debug.log(buffer.toString());
}//if//
else {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(outputFile.getAbsolutePath(), false);
fout.write(buffer.toString().getBytes());
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
finally {
if(fout != null) {
try {
fout.close();
}//try//
catch(Throwable e) {
//Ignored.//
}//catch//
}//if//
}//finally//
}//else//
}//try//
catch(Throwable e) {
//Fill in as much of the buffer as we can so we can have some kind of output.//
if((type != null) && (buffer.length() == 0)) {
try {
type.toString(buffer, 0);
}//try//
catch(Throwable e2) {
//Ignore//
}//catch//
}//if//
System.out.println(buffer);
throw e;
}//catch//
finally {
if(in != null) {
try {
in.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
if(bytesIn != null) {
try {
bytesIn.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
}//finally//
}//processClassFile()//
}//FormatSupport//

View File

@@ -0,0 +1,672 @@
package com.de22.javabytecode.code;
import java.io.IOException;
import com.common.debug.*;
import com.common.io.StandardOutputStream;
import com.de22.javabytecode.*;
import com.de22.javabytecode.util.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Supports method building.
*/
public class MethodSupport {
public static final int I = 0; //Integer
public static final int L = 1; //Long
public static final int F = 2; //Float
public static final int D = 3; //Double
public static final int A = 4; //Object
public static final byte INVOKE_INTERFACE = 1;
public static final byte INVOKE_VIRTUAL = 2;
public static final byte INVOKE_SPECIAL = 3;
public static final byte INVOKE_STATIC = 4;
private Type type = null;
/**
* MethodSupport constructor.
*/
private MethodSupport() {
super();
}//MethodSupport()//
/**
* MethodSupport constructor.
*/
public MethodSupport(Type type) {
super();
this.type = type;
}//MethodSupport()//
/**
* Casts the item on the top of the stack to the desired type.
* The stack size is unaffected.
* @param typeIndex The index of the cast type in the ConstantPool.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void cast(short typeIndex, StandardOutputStream out, StackTracker stack) throws IOException {
if(typeIndex != 0) {
out.writeByte((byte) 192); //checkcast
out.writeShort(typeIndex);
}//if//
}//cast()//
/**
* Pops two long values from the stack and compares them, and pushes the result on the stack.
* The stack is decremented by 4 and incremented by 1. The result is pushed on the stack as 1 where long1>long2, -1 where long1<long2, and 0 where long1==long2.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void compareLongs(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 148); //lcmp
stack.decrement(3);
}//compareLongs()//
/**
* Creates an array and pushes it on the stack.
* The array size is pushed on the stack and then popped off and the new array is pushed on the stack.
* @param arraySize The size of the array.
* @param arrayType The array's type which must be one of the TYPE_* identifiers defined in this class.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
* @see #TYPE_BOOLEAN
* @see #TYPE_BYTE
* @see #TYPE_CHAR
* @see #TYPE_SHORT
* @see #TYPE_INT
* @see #TYPE_FLOAT
* @see #TYPE_LONG
* @see #TYPE_DOUBLE
*/
public void createArray(int arraySize, byte arrayType, StandardOutputStream out, StackTracker stack) throws IOException {
push(arraySize, out, stack);
out.writeByte((byte) 188);
out.writeByte((byte) arrayType);
stack.increment();
}//createArray()//
/**
* Pops two int values from the stack and computes the remainder of dividing the first by the second i1 % i2 them, and pushes the result on the stack.
* The stack is decremented by 2 and incremented by 1.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void imod(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 112); //irem - Gets the remainder using: value1 % value2//
stack.decrement();
}//imod()//
/**
* Invokes the specified method using the object reference and arguments on the stack.
* <p>The caller should already have placed the object reference (except if this is a static method call) and parameters on the stack.<p>
* @param type The type object representing the compiling class.
* @param method The method being called.
* @param out The output stream for the class byte codes.
* @param stack The stack tracker that is keeping track of the current stack size.
* @return The number of of method return value words placed on the stack.
*/
public int invoke(java.lang.reflect.Method method, StandardOutputStream out, StackTracker stack) throws IOException {
Class[] parameters = method.getParameterTypes();
short methodIndex = type.addConstantMethod(method.getDeclaringClass(), method.getReturnType(), method.getName(), parameters);
int retVal = 0;
int argumentSize = 0;
for(int index = 0; index < parameters.length; index++) {
argumentSize += ((parameters[index].equals(Long.TYPE)) || (parameters[index].equals(Double.TYPE))) ? 2 : 1;
}//for//
if(method.getDeclaringClass().isInterface()) {
//Interface//
out.writeByte((byte) 185); //(-argumentSize -1 +returnValueSize) invokeinterface.//
out.writeShort((short) methodIndex);
out.writeByte((byte) (argumentSize + 1)); //The number of words to pull off the stack.//
out.writeByte((byte) 0); //Required to be 0.//
stack.decrement(argumentSize + 1);
}//if//
else if((method.getName().equals("<init>")) || (method.getName().equals("<cinit>")) || (java.lang.reflect.Modifier.isPrivate(method.getModifiers())) || (method.getClass().equals(type.getClass().getSuperclass()))) {
//Special//
out.writeByte((byte) 183); //(-argumentSize -1 +returnValueSize) invokevirtual.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//else if//
else if(java.lang.reflect.Modifier.isStatic(method.getModifiers())) {
//Static//
out.writeByte((byte) 184); //(-argumentSize +returnValueSize) invokestatic.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize);
}//else if//
else {
//Virtual//
out.writeByte((byte) 182); //(-argumentSize -1 +returnValueSize) invokevirtual.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//else//
//Increment the stack to reflect the methods return value.//
if((method.getReturnType().equals(Long.TYPE)) || (method.getReturnType().equals(Double.TYPE))) {
stack.increment(2);
retVal = 2;
}//if//
else if(!method.getReturnType().equals(Void.TYPE)) {
stack.increment();
retVal = 1;
}//else if//
return retVal;
}//invoke()//
/**
* Invokes the specified method on the class being built using the object reference and arguments on the stack.
* <p>The caller should already have placed the object reference (except if this is a static method call) and parameters on the stack.<p>
* @param methodName The name of the method being called.
* @param parameters The parameter types that the method defines.
* @param returnType The method's return type.
* @param out The output stream for the class byte codes.
* @param stack The stack tracker that is keeping track of the current stack size.
* @return The number of of method return value words placed on the stack.
*/
public int invokeSuper(String methodName, Class[] parameters, Class returnType, boolean isStatic, StandardOutputStream out, StackTracker stack) throws IOException {
short methodIndex = type.addConstantMethod(null, returnType, methodName, parameters);
int retVal = 0;
int argumentSize = 0;
for(int index = 0; index < parameters.length; index++) {
argumentSize += ((parameters[index].equals(Long.TYPE)) || (parameters[index].equals(Double.TYPE))) ? 2 : 1;
}//for//
if((methodName.equals("<init>")) || (methodName.equals("<cinit>")) || (!isStatic)) {
//Special//
out.writeByte((byte) 183); //(-argumentSize -1 +returnValueSize) invokespecial.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//if//
else {
//Static//
out.writeByte((byte) 184); //(-argumentSize +returnValueSize) invokestatic.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize);
}//else//
//Increment the stack to reflect the methods return value.//
if((returnType.equals(Long.TYPE)) || (returnType.equals(Double.TYPE))) {
stack.increment(2);
retVal = 2;
}//if//
else if(!returnType.equals(Void.TYPE)) {
stack.increment();
retVal = 1;
}//else if//
return retVal;
}//invokeSuper()//
/**
* Invokes the specified method on the class being built using the object reference and arguments on the stack.
* <p>The caller should already have placed the object reference (except if this is a static method call) and parameters on the stack.<p>
* @param methodName The name of the method being called.
* @param parameters The parameter types that the method defines.
* @param returnType The method's return type.
* @param out The output stream for the class byte codes.
* @param stack The stack tracker that is keeping track of the current stack size.
* @return The number of of method return value words placed on the stack.
*/
public int invokeThis(String methodName, Class[] parameters, Class returnType, boolean isStatic, StandardOutputStream out, StackTracker stack) throws IOException {
short methodIndex = type.addConstantMethod(null, returnType, methodName, parameters);
int retVal = 0;
int argumentSize = 0;
for(int index = 0; index < parameters.length; index++) {
argumentSize += ((parameters[index].equals(Long.TYPE)) || (parameters[index].equals(Double.TYPE))) ? 2 : 1;
}//for//
if((methodName.equals("<init>")) || (methodName.equals("<cinit>"))) {
//Special//
out.writeByte((byte) 183); //(-argumentSize -1 +returnValueSize) invokespecial.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//if//
else if(isStatic) {
//Static//
out.writeByte((byte) 184); //(-argumentSize +returnValueSize) invokestatic.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize);
}//else if//
else {
//Virtual//
out.writeByte((byte) 182); //(-argumentSize -1 +returnValueSize) invokevirtual.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//else//
//Increment the stack to reflect the methods return value.//
if((returnType.equals(Long.TYPE)) || (returnType.equals(Double.TYPE))) {
stack.increment(2);
retVal = 2;
}//if//
else if(!returnType.equals(Void.TYPE)) {
stack.increment();
retVal = 1;
}//else if//
return retVal;
}//invokeThis()//
/**
* Jumps the code pointer by <code>offset</code> amount.
* The stack is unaffected.
* <p>Warning: The jump offset will be adjusted to take into account the bytes of code that perform the jump. The caller should not need to take this into account.
* @param offset The amount to jump where a negative value would jump backward in the code, and a positive value jumps forward.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void jump(int offset, StandardOutputStream out, StackTracker stack) throws IOException {
//Adjust the offset to account for the added code of performing the jump.//
if(offset >= 0) {
offset += 3;
if(offset > 32767) {
offset += 2;
}//if//
}//if//
//Used the short jump when possible.//
if((offset < 32768) && (offset > -32769)) {
out.writeByte((byte) 167); //goto//
out.writeShort((short) offset);
}//if//
else {
out.writeByte((byte) 200); //goto_w//
out.writeInt(offset);
}//else//
}//jump()//
/**
* Pops two long values from the stack and computes the remainder of dividing the first by the second l1 % l2 them, and pushes the result on the stack.
* The stack is decremented by 4 and incremented by 2.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void lmod(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 113); //lrem - Gets the remainder using: value1 % value2//
stack.decrement(2);
}//lmod()//
/**
* Pops the value of a local variable onto the stack.
* The stack is incremented by one or two depending on the local variable's type.
* @param local The number identifying the local variable.
* @param type The local variable's type. All valid types are defined by this class as identifiers and are listed below.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
* @see #I
* @see #L
* @see #F
* @see #D
* @see #A
*/
public void load(byte local, int type, StandardOutputStream out, StackTracker stack) throws IOException {
switch(type) {
case I: {
switch(local) {
case 0: {
out.writeByte((byte) 26); //iload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 27); //iload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 28); //iload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 29); //iload_3//
break;
}//case//
default: {
out.writeByte((byte) 21); //iload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment();
break;
}//case//
case L: {
switch(local) {
case 0: {
out.writeByte((byte) 30); //lload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 31); //lload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 32); //lload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 33); //lload_3//
break;
}//case//
default: {
out.writeByte((byte) 22); //lload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment(2);
break;
}//case//
case F: {
switch(local) {
case 0: {
out.writeByte((byte) 34); //fload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 35); //fload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 36); //fload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 37); //fload_3//
break;
}//case//
default: {
out.writeByte((byte) 23); //fload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment();
break;
}//case//
case D: {
switch(local) {
case 0: {
out.writeByte((byte) 38); //dload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 39); //dload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 40); //dload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 41); //dload_3//
break;
}//case//
default: {
out.writeByte((byte) 24); //dload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment(2);
break;
}//case//
case A: {
switch(local) {
case 0: {
out.writeByte((byte) 42); //aload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 43); //aload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 44); //aload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 45); //aload_3//
break;
}//case//
default: {
out.writeByte((byte) 25); //aload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment();
break;
}//case//
default: {
//Must be I, L, F, D, or A//
Debug.halt();
throw new RuntimeException("Error: Unable to continue processing the class due to an internal error.");
}//default//
}//switch//
}//load()//
/**
* @see load(byte, Class, StandardOutputStream, StackTracker)
*/
public void load(byte local, Class type, StandardOutputStream out, StackTracker stack) throws IOException {
int typeCode;
if(type.isPrimitive()) {
if((type.equals(Integer.TYPE)) || (type.equals(Character.TYPE)) || (type.equals(Short.TYPE)) || (type.equals(Boolean.TYPE)) || (type.equals(Byte.TYPE))) {
typeCode = I;
}//if//
else if(type.equals(Long.TYPE)) {
typeCode = L;
}//else if//
else if(type.equals(Float.TYPE)) {
typeCode = F;
}//else if//
else if(type.equals(Double.TYPE)) {
typeCode = D;
}//else if//
else {
Debug.halt();
typeCode = A;
}//else//
}//if//
else {
typeCode = A;
}//else//
load(local, typeCode, out, stack);
}//load()//
/**
* Converts a long value on the stack to an int value.
* Pops a long value from the stack and pushes an int value which decrements the stack size by one.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void long2int(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 136); //l2i//
stack.decrement(1);
}//long2int()//
/**
* Adds a return statement to the type to return the method's return value from the stack.
* The return value will be popped from the stack. The stack will be incremented by one or two (for a long our double return value).
* @param type The method's return type.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void methodReturn(Class type, StandardOutputStream out, StackTracker stack) throws IOException {
boolean decrement = true;
if(type.isPrimitive()) {
if(type.equals(Integer.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//if//
else if(type.equals(Boolean.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else if(type.equals(Long.TYPE)) {
out.writeByte((byte) 173); //(-1) lreturn -> Return long//
stack.decrement(); //Account for double size value
}//else if//
else if(type.equals(Short.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else if(type.equals(Float.TYPE)) {
out.writeByte((byte) 174); //(-1) freturn -> Return float//
}//else if//
else if(type.equals(Double.TYPE)) {
out.writeByte((byte) 175); //(-1) dreturn -> Return double//
stack.decrement(); //Account for double size value//
}//else if//
else if(type.equals(Character.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else if(type.equals(Byte.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else {
//Must be VOID.//
if(stack.getStackSize() == 1) {
out.writeByte((byte) 87); //(0) pop -> Remove the remaining item on the local stack//
}//if//
else if(stack.getStackSize() > 1) {
Debug.log("Error: The stack size should be one or zero when appending a method return.");
}//else if//
else {
decrement = false;
}//else//
out.writeByte((byte) 177); //(0) return -> Return nothing//
}//else//
}//if//
else {
//An object type of return.//
out.writeByte((byte) 192); //(0) checkcast -> cast the local object to it's proper type//
out.writeShort((short) this.type.addConstantType(type)); //The index of the class to cast to//
out.writeByte((byte) 176); //(-1) areturn -> Return object reference//
}//else//
if(decrement) {
stack.decrement();
}//if//
}//methodReturn()//
/**
* Pushes a constant value onto the stack.
* The constant value or a reference to the constant value in the constant pool will be pushed on the stack. The stack will be incremented by one.
* @param value The value to place on the stack.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void push(int value, StandardOutputStream out, StackTracker stack) throws IOException {
switch(value) {
case -1: {
out.writeByte((byte) 2); //iconst_m1
stack.increment();
break;
}//case//
case 0: {
out.writeByte((byte) 3); //iconst_0
stack.increment();
break;
}//case//
case 1: {
out.writeByte((byte) 4); //iconst_1
stack.increment();
break;
}//case//
case 2: {
out.writeByte((byte) 5); //iconst_2
stack.increment();
break;
}//case//
case 3: {
out.writeByte((byte) 6); //iconst_3
stack.increment();
break;
}//case//
case 4: {
out.writeByte((byte) 7); //iconst_4
stack.increment();
break;
}//case//
case 5: {
out.writeByte((byte) 8); //iconst_5
stack.increment();
break;
}//case//
default: {
if((value < 128) && (value > -129)) {
out.writeByte((byte) 16); //bipush//
out.writeByte((byte) value);
stack.increment();
}//if//
else if((value < 32768) && (value > -32769)) {
out.writeByte((byte) 17); //sipush//
out.writeShort((short) value);
stack.increment();
}//else if//
else {
short index = type.addConstantInt(value);
pushConstant(index, out, stack);
}//else//
break;
}//default//
}//switch//
}//push()//
/**
* Pushes a constant long (wide) value onto the stack.
* The constant value or a reference to the constant value in the constant pool will be pushed on the stack. The stack will be incremented by two.
* @param value The value to place on the stack.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void push(long value, StandardOutputStream out, StackTracker stack) throws IOException {
if(value == 0) {
out.writeByte((byte) 9); //lconst_0//
stack.increment(2);
}//if//
else if(value == 1) {
out.writeByte((byte) 10); //lconst_1//
stack.increment(2);
}//else if//
else {
short index = type.addConstantLong(value);
pushWideConstant(index, out, stack);
}//else//
}//push()//
/**
* Pushes a constant value onto the stack using a constant value in the constant pool.
* A reference to the constant will be used to push the value on the stack. The stack will be incremented by one.
* @param index The value's index in the constant pool.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void pushConstant(short index, StandardOutputStream out, StackTracker stack) throws IOException {
if((index < 128) && (index > -129)) {
out.writeByte((byte) 18); //ldc//
out.writeByte((byte) index);
}//if//
else {
out.writeByte((byte) 19); //ldc_w//
out.writeShort(index);
}//else//
stack.increment();
}//pushConstant()//
/**
* Pushes a wide constant value onto the stack using a constant value in the constant pool.
* A reference to the constant will be used to push the wide (8 byte) value on the stack. The stack will be incremented by two.
* @param index The value's index in the constant pool.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void pushWideConstant(short index, StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 20); //ldc2_w//
out.writeShort(index);
stack.increment(2);
}//pushWideConstant()//
}//MethodSupport//

View File

@@ -0,0 +1,397 @@
package com.de22.javabytecode.code;
import com.common.util.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Defines an operation code.
*/
public class OpCode {
public static final int SIGNED_INT = 0;
public static final int UNSIGNED_INT = 1;
public static final int SIGNED_SHORT = 2;
public static final int UNSIGNED_SHORT = 3;
public static final int SIGNED_BYTE = 4;
public static final int UNSIGNED_BYTE = 5;
public static final int SHORT_CONSTANT_REF = 6; //Same as an UNSIGNED_BYTE, but identifies the param as being an index into the constant pool.//
public static final int CONSTANT_REF = 7; //Same as an UNSIGNED_SHORT, but identifies the param as being an index into the constant pool.//
private static final int[] EMPTY_INT_ARRAY = new int[0];
/** The opcode's name. */
private String name = null;
/** The opcode's general description. */
private String description = null;
/** The collection of parameter types, one for each parameter in the opcode. */
private int[] parameterTypes = null;
/** The collection of parameter descriptions, one for each parameter in the opcode. */
private IList parameterDescriptions = null;
/** The collection of parameter byte descriptions, one for each byte that follows the opcode. */
private IList parameterByteDescriptions = null;
private static IList opCodes = null;
/**
* Defines the array of all operation codes in Java.
*/
private static final OpCode[] opCodeArray = new OpCode[] {
new OpCode("nop", "Do nothing.", -9999), //00
new OpCode("aconst_null", "Push a null object reference onto the operand stack.", -9999), //01
new OpCode("iconst_m1", "Push the int constant -1 onto the operand stack.", -9999), //02
new OpCode("iconst_0", "Push the int constant 0 onto the operand stack.", -9999), //03
new OpCode("iconst_1", "Push the int constant 1 onto the operand stack.", -9999), //04
new OpCode("iconst_2", "Push the int constant 2 onto the operand stack.", -9999), //05
new OpCode("iconst_3", "Push the int constant 3 onto the operand stack.", -9999), //06
new OpCode("iconst_4", "Push the int constant 4 onto the operand stack.", -9999), //07
new OpCode("iconst_5", "Push the int constant 5 onto the operand stack.", -9999), //08
new OpCode("lconst_0", "Push the long constant 0 onto the operand stack.", -9999), //09
new OpCode("lconst_1", "Push the long constant 1 onto the operand stack.", -9999), //0A
new OpCode("fconst_0", "Push the float constant 0 onto the operand stack.", -9999), //0B
new OpCode("fconst_1", "Push the float constant 1 onto the operand stack.", -9999), //0C
new OpCode("fconst_2", "Push the float constant 2 onto the operand stack.", -9999), //0D
new OpCode("dconst_0", "Push the double constant 0 onto the operand stack.", -9999), //0E
new OpCode("dconst_1", "Push the double constant 1 onto the operand stack.", -9999), //0F
new OpCode("bipush", "Pushes a specified byte onto the operand stack as a signed int.", new int[] {SIGNED_BYTE}, new String[] {"The signed byte value."}, new String[] {"A signed byte."}, -9999), //10
new OpCode("sipush", "Pushes a specified short onto the operand stack as a signed int.", new int[] {SIGNED_SHORT}, new String[] {"The signed short value."}, new String[] {"The high byte.", "The low byte. ((byte1<<8)|byte2 = short)"}, -9999), //11
new OpCode("ldc", "Pushes a constant onto the operand stack (may be int, float, or string reference).", new int[] {SHORT_CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"An index in the ClassFile's constantPool."}, -9999), //12
new OpCode("ldc_w", "Pushes a constant onto the operand stack (may be int, float, or string reference).", new int[] {CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"The high byte of the index in the ClassFile's constantPool.", "The low byte ((highByte<<8)|lowByte = index)."}, -9999), //13
new OpCode("ldc2_w", "Pushes a constant onto the operand stack (may be long, or double).", new int[] {CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"The high byte of the index in the ClassFile's constantPool.", "The low byte ((highByte<<8)|lowByte = index)."}, -9999), //14
new OpCode("iload", "Load an int from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //15
new OpCode("lload", "Load a long from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //16
new OpCode("fload", "Load a float from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //17
new OpCode("dload", "Load a double from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //18
new OpCode("aload", "Load an object reference from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //19
new OpCode("iload_0", "Load an int from the local variable 0 onto the operand stack.", -9999), //1A
new OpCode("iload_1", "Load an int from the local variable 1 onto the operand stack.", -9999), //1B
new OpCode("iload_2", "Load an int from the local variable 2 onto the operand stack.", -9999), //1C
new OpCode("iload_3", "Load an int from the local variable 3 onto the operand stack.", -9999), //1D
new OpCode("lload_0", "Load a long from the local variable 0 onto the operand stack.", -9999), //1E
new OpCode("lload_1", "Load a long from the local variable 1 onto the operand stack.", -9999), //1F
new OpCode("lload_2", "Load a long from the local variable 2 onto the operand stack.", -9999), //20
new OpCode("lload_3", "Load a long from the local variable 3 onto the operand stack.", -9999), //21
new OpCode("fload_0", "Load a float from the local variable 0 onto the operand stack.", -9999), //22
new OpCode("fload_1", "Load a float from the local variable 1 onto the operand stack.", -9999), //23
new OpCode("fload_2", "Load a float from the local variable 2 onto the operand stack.", -9999), //24
new OpCode("fload_3", "Load a float from the local variable 3 onto the operand stack.", -9999), //25
new OpCode("dload_0", "Load a double from the local variable 0 onto the operand stack.", -9999), //26
new OpCode("dload_1", "Load a double from the local variable 1 onto the operand stack.", -9999), //27
new OpCode("dload_2", "Load a double from the local variable 2 onto the operand stack.", -9999), //28
new OpCode("dload_3", "Load a double from the local variable 3 onto the operand stack.", -9999), //29
new OpCode("aload_0", "Load an object reference from the local variable 0 onto the operand stack.", -9999), //2A
new OpCode("aload_1", "Load an object reference from the local variable 1 onto the operand stack.", -9999), //2B
new OpCode("aload_2", "Load an object reference from the local variable 2 onto the operand stack.", -9999), //2C
new OpCode("aload_3", "Load an object reference from the local variable 3 onto the operand stack.", -9999), //2D
new OpCode("iaload", "", -9999), //2E
new OpCode("laload", "", -9999), //2F
new OpCode("faload", "", -9999), //30
new OpCode("daload", "", -9999), //31
new OpCode("aaload", "", -9999), //32
new OpCode("baload", "", -9999), //33
new OpCode("caload", "", -9999), //34
new OpCode("saload", "", -9999), //35
new OpCode("istore", "Pops an int off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //36
new OpCode("lstore", "Pops a long off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //37
new OpCode("fstore", "Pops a float off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //38
new OpCode("dstore", "Pops a double off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //39
new OpCode("astore", "Pops an object reference off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //3A
new OpCode("istore_0", "Pops an int off the operand stack & stores it in the local variable 0.", -9999), //3B
new OpCode("istore_1", "Pops an int off the operand stack & stores it in the local variable 1.", -9999), //3C
new OpCode("istore_2", "Pops an int off the operand stack & stores it in the local variable 2.", -9999), //3D
new OpCode("istore_3", "Pops an int off the operand stack & stores it in the local variable 3.", -9999), //3E
new OpCode("lstore_0", "Pops an int off the operand stack & stores it in the local variable 0.", -9999), //3F
new OpCode("lstore_1", "Pops a long off the operand stack & stores it in the local variable 1.", -9999), //40
new OpCode("lstore_2", "Pops a long off the operand stack & stores it in the local variable 2.", -9999), //41
new OpCode("lstore_3", "Pops a long off the operand stack & stores it in the local variable 3.", -9999), //42
new OpCode("fstore_0", "Pops a float off the operand stack & stores it in the local variable 0.", -9999), //43
new OpCode("fstore_1", "Pops a float off the operand stack & stores it in the local variable 1.", -9999), //44
new OpCode("fstore_2", "Pops a float off the operand stack & stores it in the local variable 2.", -9999), //45
new OpCode("fstore_3", "Pops a float off the operand stack & stores it in the local variable 3.", -9999), //46
new OpCode("dstore_0", "Pops a double off the operand stack & stores it in the local variable 0.", -9999), //47
new OpCode("dstore_1", "Pops a double off the operand stack & stores it in the local variable 1.", -9999), //48
new OpCode("dstore_2", "Pops a double off the operand stack & stores it in the local variable 2.", -9999), //49
new OpCode("dstore_3", "Pops a double off the operand stack & stores it in the local variable 3.", -9999), //4A
new OpCode("astore_0", "Pops an object reference off the operand stack & stores it in the local variable 0.", -9999), //4B
new OpCode("astore_1", "Pops an object reference off the operand stack & stores it in the local variable 1.", -9999), //4C
new OpCode("astore_2", "Pops an object reference off the operand stack & stores it in the local variable 2.", -9999), //4D
new OpCode("astore_3", "Pops an object reference off the operand stack & stores it in the local variable 3.", -9999), //4E
new OpCode("iastore", "Stores a value into an int array at an index (...,arrayref,index,value -> ...).", -9999), //4F
new OpCode("lastore", "Stores a value into a long array at an index (...,arrayref,index,value -> ...).", -9999), //50
new OpCode("fastore", "Stores a value into a float array at an index (...,arrayref,index,value -> ...).", -9999), //51
new OpCode("dastore", "Stores a value into a double array at an index (...,arrayref,index,value -> ...).", -9999), //52
new OpCode("aastore", "Stores a value into an object array at an index (...,arrayref,index,value -> ...).", -9999), //53
new OpCode("bastore", "Stores a value into a byte/boolean array at an index (...,arrayref,index,value -> ...).", -9999), //54
new OpCode("castore", "Stores a value into a char array at an index (...,arrayref,index,value -> ...).", -9999), //55
new OpCode("sastore", "Stores a value into a short array at an index (...,arrayref,index,value -> ...).", -9999), //56
new OpCode("pop", "Pops the top word off the operand stack.", -9999), //57
new OpCode("pop2", "Pops the top 2 words off the operand stack.", -9999), //58
new OpCode("dup", "Duplicates the top word on the operand stack.", -9999), //59
new OpCode("dup_x1", "Duplicates the top word on the operand stack & puts the duplicate one down.", -9999), //5A
new OpCode("dup_x2", "Duplicates the top word on the operand stack & puts the duplicate two down.", -9999), //5B
new OpCode("dup2", "Duplicates the top 2 words on the operand stack.", -9999), //5C
new OpCode("dup2_x1", "Duplicates the top 2 words on the operand stack & puts the duplicates one down.", -9999), //5D
new OpCode("dup2_x2", "Duplicates the top 2 words on the operand stack & puts the duplicates two down.", -9999), //5E
new OpCode("swap", "Swaps the top two words on the operand stack.", -9999), //5F
new OpCode("iadd", "Pops two int values off the operand stack and pushes back (value1+value2).", -9999), //60
new OpCode("ladd", "Pops two long values off the operand stack and pushes back (value1+value2).", -9999), //61
new OpCode("fadd", "Pops two float values off the operand stack and pushes back (value1+value2).", -9999), //62
new OpCode("dadd", "Pops two double values off the operand stack and pushes back (value1+value2).", -9999), //63
new OpCode("isub", "Pops two int values off the operand stack and pushes back (value1-value2).", -9999), //64
new OpCode("lsub", "Pops two long values off the operand stack and pushes back (value1-value2).", -9999), //65
new OpCode("fsub", "Pops two float values off the operand stack and pushes back (value1-value2).", -9999), //66
new OpCode("dsub", "Pops two double values off the operand stack and pushes back (value1-value2).", -9999), //67
new OpCode("imul", "Pops two int values off the operand stack and pushes back (value1*value2).", -9999), //68
new OpCode("lmul", "Pops two long values off the operand stack and pushes back (value1*value2).", -9999), //69
new OpCode("fmul", "Pops two float values off the operand stack and pushes back (value1*value2).", -9999), //6A
new OpCode("dmul", "Pops two double values off the operand stack and pushes back (value1*value2).", -9999), //6B
new OpCode("idiv", "Pops two int values off the operand stack and pushes back (value1/value2).", -9999), //6C
new OpCode("ldiv", "Pops two long values off the operand stack and pushes back (value1/value2).", -9999), //6D
new OpCode("fdiv", "Pops two float values off the operand stack and pushes back (value1/value2).", -9999), //6E
new OpCode("ddiv", "Pops two double values off the operand stack and pushes back (value1/value2).", -9999), //6F
new OpCode("irem", "Pops two int values off the operand stack and pushes back (value1%value2).", -9999), //70
new OpCode("lrem", "Pops two long values off the operand stack and pushes back (value1%value2).", -9999), //71
new OpCode("frem", "Pops two float values off the operand stack and pushes back (value1%value2).", -9999), //72
new OpCode("drem", "Pops two double values off the operand stack and pushes back (value1%value2).", -9999), //73
new OpCode("ineg", "Pops an int value off the operand stack and pushes back (0 - value).", -9999), //74
new OpCode("lneg", "Pops a long value off the operand stack and pushes back (0 - value).", -9999), //75
new OpCode("fneg", "Pops a float value off the operand stack and pushes back (0 - value).", -9999), //76
new OpCode("dneg", "Pops a double value off the operand stack and pushes back (0 - value).", -9999), //77
new OpCode("ishl", "", -9999), //78
new OpCode("lshl", "", -9999), //79
new OpCode("ishr", "", -9999), //7A
new OpCode("lshr", "", -9999), //7B
new OpCode("iushr", "", -9999), //7C
new OpCode("lushr", "", -9999), //7D
new OpCode("iand", "", -9999), //7E
new OpCode("land", "", -9999), //7F
new OpCode("ior", "", -9999), //80
new OpCode("lor", "", -9999), //81
new OpCode("ixor", "", -9999), //82
new OpCode("lxor", "", -9999), //83
new OpCode("iinc", "Increments a local variable by a given constant.", new int[] {UNSIGNED_BYTE, SIGNED_BYTE}, new String[] {"The index to an integer local variable in the current frame.", "The signed byte (converted to a sign extended integer) used to modify the local variable referenced by the first parameter."}, new String[] {"The local variable index (int).", "The signed constant value (int)"}, -9999), //84
new OpCode("i2l", "", -9999), //85
new OpCode("i2f", "", -9999), //86
new OpCode("i2d", "", -9999), //87
new OpCode("l2i", "", -9999), //88
new OpCode("l2f", "", -9999), //89
new OpCode("l2d", "", -9999), //8A
new OpCode("f2i", "", -9999), //8B
new OpCode("f2l", "", -9999), //8C
new OpCode("f2d", "", -9999), //8D
new OpCode("d2i", "", -9999), //8E
new OpCode("d2l", "", -9999), //8F
new OpCode("d2f", "", -9999), //90
new OpCode("i2b", "", -9999), //91
new OpCode("i2c", "", -9999), //92
new OpCode("i2s", "", -9999), //93
new OpCode("lcmp", "", -9999), //94
new OpCode("fcmpl", "", -9999), //95
new OpCode("fcmpg", "", -9999), //96
new OpCode("dcmpl", "", -9999), //97
new OpCode("dcmpg", "", -9999), //98
new OpCode("ifeq", "Pops an int value off the operand stack and checks for (value == 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //99
new OpCode("ifne", "Pops an int value off the operand stack and checks for (value != 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9A
new OpCode("iflt", "Pops an int value off the operand stack and checks for (value < 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9B
new OpCode("ifge", "Pops an int value off the operand stack and checks for (value >= 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9C
new OpCode("ifgt", "Pops an int value off the operand stack and checks for (value > 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9D
new OpCode("ifle", "Pops an int value off the operand stack and checks for (value <= 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9E
new OpCode("if_icmpeq", "Pops two int values off the operand stack and checks for (value1 == value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9F
new OpCode("if_icmpne", "Pops two int values off the operand stack and checks for (value1 != value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A0
new OpCode("if_icmplt", "Pops two int values off the operand stack and checks for (value1 < value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A1
new OpCode("if_icmpge", "Pops two int values off the operand stack and checks for (value1 >= value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A2
new OpCode("if_icmpgt", "Pops two int values off the operand stack and checks for (value1 > value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A3
new OpCode("if_icmple", "Pops two int values off the operand stack and checks for (value1 <= value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A4
new OpCode("if_acmpeq", "Pops two object references off the operand stack and checks for (value1 == value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A5
new OpCode("if_acmpne", "Pops two object references off the operand stack and checks for (value1 != value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A6
new OpCode("goto", "Performs a branch operation.", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset."}, new String[] {"The high byte of the signed 16bit jump offset.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A7
new OpCode("jsr", "", -9999), //A8
new OpCode("ret", "", -9999), //A9
new OpCode("tableswitch", "", -9999), //AA
new OpCode("lookupswitch", "", -9999), //AB
new OpCode("ireturn", "Return an int (off the operand stack).", -9999), //AC
new OpCode("lreturn", "Return a long (off the operand stack).", -9999), //AD
new OpCode("freturn", "Return a float (off the operand stack).", -9999), //AE
new OpCode("dreturn", "Return a double (off the operand stack).", -9999), //AF
new OpCode("areturn", "Return a reference (off the operand stack).", -9999), //B0
new OpCode("return", "Return from this method.", -9999), //B1
new OpCode("getstatic", "Pops an object reference off the operand stack and pushes the value (1 or 2 words) of that object's static attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B2
new OpCode("putstatic", "Pops an object reference and the value (1 or 2 words) off the operand stack and sets the value of that object's static attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B3
new OpCode("getfield", "Pops an object reference off the operand stack and pushes the value (1 or 2 words) of that object's attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B4
new OpCode("putfield", "Pops an object reference and the value (1 or 2 words) off the operand stack and sets the value of that object's attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B5
new OpCode("invokevirtual", "Pops an object reference, all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantMethodReference in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //B6
new OpCode("invokespecial", "Pops an object reference, all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantMethodReference in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //B7
new OpCode("invokestatic", "Pops all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantMethodReference in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //B8
new OpCode("invokeinterface", "Pops an object reference, all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF, UNSIGNED_BYTE, UNSIGNED_BYTE}, new String[] {"The index of a ConstantInterfaceMethodReference in the ClassFile's constantPool.", "The number of words (plus one) that should be popped off the operand stack (to be used as parameter(s)).", "Reserved; Must be 0."}, new String[] {"The highbyte of an index of a ConstantInterfaceMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index).", "The number of words (plus one) that should be popped off the operand stack (to be used as parameter(s)).", "Reserved; Must be 0."}, -9999), //B9
new OpCode("xxxunusedxxx", "", -9999), //BA
new OpCode("new", "Creates a new object of the given type.", new int[] {CONSTANT_REF}, new String[] {"The constant reference to the object type."}, new String[] {"", ""}, -9999), //BB
new OpCode("newarray", "Creates a new array whose size is an int popped off the stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The array type code."}, new String[] {"The array type code."}, -9999), //BC
new OpCode("anewarray", "Pops an int (count) off the stack & creates a new array of size count.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantClass in the ClassFile's constantPool (The type of the array)."}, new String[] {"The highbyte of an index of a ConstantClass in the ClassFile's constantPool (The type of the array).", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //BD
new OpCode("arraylength", "", -9999), //BE
new OpCode("athrow", "", -9999), //BF
new OpCode("checkcast", "Checks the object reference on the operand stack is castable to the given ConstantClass", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantClass in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantClass in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //C0
new OpCode("instanceof", "", new int[] {CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"The high byte of the index in the ClassFile's constantPool.", "The low byte ((highByte<<8)|lowByte = index)."}, -9999), //C1
new OpCode("monitorenter", "", -9999), //C2
new OpCode("monitorexit", "", -9999), //C3
new OpCode("wide", "", -9999), //C4
new OpCode("multianewarray", "", -9999), //C5
new OpCode("ifnull", "Pops an object reference value off the operand stack and checks for (value == null).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //C6
new OpCode("ifnonnull", "Pops an object reference value off the operand stack and checks for (value != null).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //C7
new OpCode("goto_w", "", new int[] {SIGNED_INT}, new String[] {"The signed 32bit jump offset."}, new String[] {"The first (high) byte of the signed 32bit jump offset.", "The second byte of the offset.", "The third byte of the offset.", "The fourth (low) byte of the offset. ((byte1<<24)|(byte2<<24)|(byte3<<24)|(byte4) = offset)"}, -9999), //C8
new OpCode("jsr_w", "", -9999), //C9
new OpCode("breakpoint", "Reserved", -9999), //CA
new OpCode("ldc_quick", "", -9999), //CB
new OpCode("ldc_w_quick", "", -9999), //CC
new OpCode("ldc2_w_quick", "", -9999), //CD
new OpCode("getfield_quick", "", -9999), //CE
new OpCode("putfield_quick", "", -9999), //CF
new OpCode("getfield2_quick", "", -9999), //D0
new OpCode("putfield2_quick", "", -9999), //D1
new OpCode("getstatic_quick", "", -9999), //D2
new OpCode("putstatic_quick", "", -9999), //D3
new OpCode("getstatic2_quick", "", -9999), //D4
new OpCode("putstatic2_quick", "", -9999), //D5
new OpCode("invokevirtual_quick", "", -9999), //D6
new OpCode("invokenonvirtual_quick", "", -9999), //D7
new OpCode("invokesuper_quick", "", -9999), //D8
new OpCode("invokestatic_quick", "", -9999), //D9
new OpCode("invokeinterface_quick", "", -9999), //DA
new OpCode("invokevirtualobject_quick", "", -9999), //DB
new OpCode("xxx", "", -9999), //DC
new OpCode("new_quick", "", -9999), //DD
new OpCode("anewarray_quick", "", -9999), //DE
new OpCode("multianewarray_quick", "", -9999), //DF
new OpCode("checkcast_quick", "", -9999), //E0
new OpCode("instanceof_quick", "", -9999), //E1
new OpCode("invokevirtual_quick_w", "", -9999), //E2
new OpCode("getfield_quick_w", "", -9999), //E3
new OpCode("putfield_quick_w", "", -9999), //E4
new OpCode("xxx", "", -9999), //E5
new OpCode("xxx", "", -9999), //E6
new OpCode("xxx", "", -9999), //E7
new OpCode("xxx", "", -9999), //E8
new OpCode("xxx", "", -9999), //E9
new OpCode("xxx", "", -9999), //EA
new OpCode("xxx", "", -9999), //EB
new OpCode("xxx", "", -9999), //EC
new OpCode("xxx", "", -9999), //ED
new OpCode("xxx", "", -9999), //EE
new OpCode("xxx", "", -9999), //EF
new OpCode("xxx", "", -9999), //F0
new OpCode("xxx", "", -9999), //F1
new OpCode("xxx", "", -9999), //F2
new OpCode("xxx", "", -9999), //F3
new OpCode("xxx", "", -9999), //F4
new OpCode("xxx", "", -9999), //F5
new OpCode("xxx", "", -9999), //F6
new OpCode("xxx", "", -9999), //F7
new OpCode("xxx", "", -9999), //F8
new OpCode("xxx", "", -9999), //F9
new OpCode("xxx", "", -9999), //FA
new OpCode("xxx", "", -9999), //FB
new OpCode("xxx", "", -9999), //FC
new OpCode("xxx", "", -9999), //FD
new OpCode("impdep1", "Reserved", -9999), //FE
new OpCode("impdep2", "Reserved", -9999) //FF
};//opCodes//
/**
* OpCode constructor.
*/
private OpCode() {
super();
}//OpCode()//
/**
* OpCode constructor.
* @param name The operational code name.
* @param description The useful description of this op code.
* @param extra The number of extra bytes following the op code.
*/
private OpCode(String name, String description, int extra) {
this.name = name;
this.description = description;
this.parameterTypes = EMPTY_INT_ARRAY;
this.parameterDescriptions = LiteList.EMPTY_LIST;
this.parameterByteDescriptions = LiteList.EMPTY_LIST;
}//OpCode()//
/**
* OpCode constructor.
* @param name The operational code name.
* @param description The useful description of this op code.
* @param parameterTypes
* @param parameterDescriptions
* @param parameterByteDescriptions
* @param extra The number of extra bytes following the op code.
*/
private OpCode(String name, String description, int[] parameterTypes, String[] parameterDescriptions, String[] parameterByteDescriptions, int extra) {
this.name = name;
this.description = description;
this.parameterTypes = parameterTypes;
this.parameterDescriptions = parameterDescriptions != null ? new LiteList(parameterDescriptions) : LiteList.EMPTY_LIST;
this.parameterDescriptions.isChangeable(false);
this.parameterByteDescriptions = parameterByteDescriptions != null ? new LiteList(parameterByteDescriptions) : LiteList.EMPTY_LIST;
this.parameterByteDescriptions.isChangeable(false);
}//OpCode()//
/**
* Gets the operational code's description.
* @return The description of the OpCode.
*/
public String getDescription() {
return description;
}//getDescription()//
/**
* Gets the operational code's name.
* @return The name of the OpCode.
*/
public String getName() {
return name;
}//getName()//
/**
* Gets the OpCode objects that represent all valid java operational codes.
* @return The ordered array of all OpCodes.
*/
public static IList getOpCodes() {
if(opCodes == null) {
synchronized(OpCode.class) {
if(opCodes == null) {
opCodes = new LiteList(opCodeArray);
opCodes.isChangeable(false);
}//if//
}//synchronized//
}//if//
return opCodes;
}//getOpCodes()//
/**
* Gets the parameter type codes (see OpCode identifiers), one for each parameter to the opcode.
* @return The collection of parameter types.
*/
public int[] getParameterTypes() {
return parameterTypes;
}//getParameterTypes()//
/**
* Gets the descriptions for each parameter in order that they occur.
* @return The ordered collection of parameter descriptions.
*/
public IList getParameterDescriptions() {
return parameterDescriptions;
}//getParameterDescriptions()//
/**
* Gets the descriptions for each parameter byte in order that they occur.
* @return The ordered collection of descriptions for each byte that follows the opcode.
*/
public IList getParameterByteDescriptions() {
return parameterByteDescriptions;
}//getParameterByteDescriptions()//
/**
* Provides a human readable representation of the OpCode.
* @return A string representation.
*/
public String toString() {
String retVal = "";
retVal += name;
for(int t = name.length(); t < 12; t++) {
retVal += " ";
}//for//
retVal += " " + description;
return retVal;
}//toString()//
}//OpCode//

View File

@@ -0,0 +1,170 @@
package com.de22.javabytecode.code;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.common.debug.Debug;
import com.common.io.ByteArrayInputStream;
import com.common.io.ByteArrayOutputStream;
import com.common.io.ObjectInputStream;
import com.common.io.ObjectOutputStream;
import com.de22.javabytecode.Type;
/**
* Copyright Declarative Engineering LLC 2007<p>
* A simple test class that reads in a class file and then writes it out without any modifications.
* This class tests the ability to read and write a class file without introducing errors.
*/
public class Test {
/**
* Reverse engineers a class file and writes it back out to 'output.class'.
* @param args The array of initialization parameters.
* args[0] = The path and file name of the class to reverse engineer.
* args[1] = The path (must exist) where the output.class file will be stored. If the file exists it will be over written.
*/
public static void main(String[] args) {
String debugText = null;
long t = System.currentTimeMillis();
try {
File file = new File(args[0]);
File path = args.length > 1 ? new File(args[1]) : null;
if(path != null && (path.isFile() || (!path.exists() && !path.mkdirs()))) {
path = null;
}//if//
if(file.getName().endsWith(".class")) {
debugText = file.getPath();
processClassFile(file, new File(path, "output.class"));
compareClassFiles(file, new File(path, "output.class"));
}//if//
}//try//
catch(Throwable e) {
Debug.log(e, "Caught while processing the class file: " + debugText);
}//catch//
Debug.log("Total time (milliseconds): " + (System.currentTimeMillis() - t));
System.exit(0);
}//main()//
/**
* Writes a file.
* @param file The file to write.
* @param bytes The bytes to place in the file.
*/
public static void writeFile(File file, byte[] bytes) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
fout.write(bytes);
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
finally {
if(fout != null) {
try {
fout.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
}//finally//
}//writeFile()//
/**
* Reads a file and returns the bytes contained there in.
* @param file The file to read.
* @return The bytes contained in the file.
*/
public static byte[] readFile(File file) {
FileInputStream fin = null;
byte[] bytes = null;
int counter = 0;
try {
fin = new FileInputStream(file);
bytes = new byte[fin.available()];
while(counter < bytes.length) {
counter += fin.read(bytes, counter, bytes.length - counter);
}//while//
fin.close();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
finally {
if(fin != null) {
try {
fin.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
}//finally//
return bytes;
}//readFile()//
/**
* Processes a class file and writes out the byte codes in a semi-readable form.
* @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method.
* @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise.
*/
private static void processClassFile(File inputFile, File outputFile) throws Throwable {
ByteArrayInputStream bin = null;
ObjectInputStream in = null;
Type type = null;
ByteArrayOutputStream bout = null;
ObjectOutputStream out = null;
try {
bin = new ByteArrayInputStream(readFile(inputFile));
in = new ObjectInputStream(bin, null, null);
type = new Type();
type.readExternal(in);
bout = new ByteArrayOutputStream(100000, false);
out = new ObjectOutputStream(bout, null);
type.writeExternal(out);
out.flush();
writeFile(outputFile, bout.toByteArray());
}//try//
catch(Throwable e) {
e.printStackTrace();
throw e;
}//catch//
}//processClassFile()//
/**
* Processes a class file and writes out the byte codes in a semi-readable form.
* @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method.
* @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise.
*/
private static void compareClassFiles(File inputFile, File outputFile) throws Throwable {
byte[] originalBytes;
byte[] modifiedBytes;
int byteLength;
originalBytes = readFile(inputFile);
modifiedBytes = readFile(outputFile);
byteLength = Math.min(originalBytes.length, modifiedBytes.length);
for(int index = 0; index < byteLength; index++) {
if(originalBytes[index] != modifiedBytes[index]) {
Debug.log("Files diverge at index " + index);
return;
}//if//
}//for//
if(originalBytes.length != modifiedBytes.length) {
Debug.log("One file has more bytes than the other.");
}//if//
else {
Debug.log("Files are exactly the same.");
}//else//
}//processClassFile()//
}//Test//

View File

@@ -0,0 +1,112 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantDouble extends Constant {
private double value = 0;
/**
* ConstantDouble constructor.
* @param type The class this constant is a member of.
*/
public ConstantDouble(Type type) {
super(type);
}//ConstantDouble()//
/**
* ConstantDouble constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantDouble(Type type, double value) {
super(type);
this.value = value;
}//ConstantDouble()//
/**
* Gets the value for this associated with this constant.
* @return The double value.
*/
public double getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantDouble) && (value == ((ConstantDouble) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 8;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_DOUBLE;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (int) Double.doubleToLongBits(value);
}//hashCode()//
/**
* Determines whether the constant takes double the constant entries in the class bytes.
* @return Whether the constant is a double size constant.
*/
public boolean isDoubleSize() {
return true;
}//isDoubleSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readDouble();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Double.toString(value) + " (Double)";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Double: " + Double.toString(value);
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Double Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeDouble(value);
}//writeExternal()//
}//ConstantDouble//

View File

@@ -0,0 +1,154 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantFieldRef extends Constant {
/** The reference to the class that defines the field. */
private short classIndex = 0;
/** The reference to the name and signature of the method. */
private short nameAndTypeIndex = 0;
/**
* ConstantFieldRef constructor.
* @param type The class this constant is a member of.
*/
public ConstantFieldRef(Type type) {
super(type);
}//ConstantFieldRef()//
/**
* ConstantFieldRef constructor.
* @param type The class this constant is a member of.
* @param classIndex The index of the class constant.
* @param nameAndTypeIndex The index of the name and type descriptor constant.
*/
public ConstantFieldRef(Type type, short classIndex, short nameAndTypeIndex) {
super(type);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}//ConstantFieldRef()//
/**
* Gets the constant pool index for the class that defines the field (a ConstantType instance).
* @return The pool index of the class constant.
*/
public short getClassIndex() {
return classIndex;
}//getClassIndex()//
/**
* Gets the constant pool index for the name and type for the field (a ConstantNameAndType instance).
* @return The pool index of the name and type constant.
*/
public short getNameAndTypeIndex() {
return nameAndTypeIndex;
}//getNameAndTypeIndex()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantFieldRef) && (((ConstantFieldRef) object).classIndex == classIndex) && (((ConstantFieldRef) object).nameAndTypeIndex == nameAndTypeIndex);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_FIELD_REF;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (classIndex << 4) | nameAndTypeIndex;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
classIndex = in.readShort();
nameAndTypeIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant definingTypeConstant = getType().getConstant(classIndex);
Constant nameAndTypeConstant = getType().getConstant(nameAndTypeIndex);
Constant fieldTypeConstant = null;
Constant fieldNameConstant = null;
if(definingTypeConstant instanceof ConstantType) {
definingTypeConstant = getType().getConstant(((ConstantType) definingTypeConstant).getNameIndex());
}//if//
if(definingTypeConstant instanceof ConstantString) {
definingTypeConstant = getType().getConstant(((ConstantString) definingTypeConstant).getStringIndex());
}//if//
if(nameAndTypeConstant instanceof ConstantNameAndType) {
fieldNameConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getNameIndex());
fieldTypeConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getDescriptorIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantType) {
fieldTypeConstant = getType().getConstant(((ConstantType) fieldTypeConstant).getNameIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantString) {
fieldTypeConstant = getType().getConstant(((ConstantString) fieldTypeConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldNameConstant instanceof ConstantString) {
fieldNameConstant = getType().getConstant(((ConstantString) fieldNameConstant).getStringIndex());
}//if//
return definingTypeConstant instanceof ConstantUtf8 && fieldTypeConstant instanceof ConstantUtf8 && fieldNameConstant instanceof ConstantUtf8 ? ((ConstantUtf8) definingTypeConstant).getValue() + "." + ((ConstantUtf8) fieldNameConstant).getValue() + " (Field Name)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Field Reference (classIndex: " + classIndex + " nameAndTypeIndex: " + nameAndTypeIndex;
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Field Reference Constant (classIndex=");
buffer.append(classIndex);
buffer.append(" nameAndTypeIndex=");
buffer.append(nameAndTypeIndex);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex);
}//writeExternal()//
}//ConstantFieldRef//

View File

@@ -0,0 +1,105 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantFloat extends Constant {
private float value = 0;
/**
* ConstantType constructor.
* @param type The class this constant is a member of.
*/
public ConstantFloat(Type type) {
super(type);
}//ConstantFloat()//
/**
* ConstantType constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantFloat(Type type, float value) {
super(type);
this.value = value;
}//ConstantFloat()//
/**
* Gets the value for this associated with this constant.
* @return The float value.
*/
public float getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantFloat) && (value == ((ConstantFloat) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_FLOAT;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return Float.floatToIntBits(value);
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readFloat();
}//readExternal()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Float: " + Float.toString(value);
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Float.toString(value) + " (Float)";
}//getPrettyValue()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Float Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeFloat(value);
}//writeExternal()//
}//ConstantFloat//

View File

@@ -0,0 +1,105 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantInteger extends Constant {
private int value = 0;
/**
* ConstantInteger constructor.
* @param type The class this constant is a member of.
*/
public ConstantInteger(Type type) {
super(type);
}//ConstantInteger()//
/**
* ConstantInteger constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantInteger(Type type, int value) {
super(type);
this.value = value;
}//ConstantInteger()//
/**
* Gets the value for this associated with this constant.
* @return The integer value.
*/
public int getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantInteger) && (value == ((ConstantInteger) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_INTEGER;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return value;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readInt();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Integer.toString(value) + " (Integer)";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Integer: " + Integer.toString(value);
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Integer Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(value);
}//writeExternal()//
}//ConstantInteger//

View File

@@ -0,0 +1,149 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a method that is defined by an interface.
*/
public class ConstantInterfaceMethodRef extends Constant {
/** The reference to the interface that defines the method. */
private short classIndex = 0;
/** The reference to the name and signature of the method. */
private short nameAndTypeIndex = 0;
/**
* ConstantInterfaceMethodRef constructor.
* @param type The class this constant is a member of.
*/
public ConstantInterfaceMethodRef(Type type) {
super(type);
}//ConstantInterfaceMethodRef()//
/**
* ConstantInterfaceMethodRef constructor.
* @param type The class this constant is a member of.
* @param classIndex The index of the class constant.
* @param nameAndTypeIndex The index of the name and type descriptor constant.
*/
public ConstantInterfaceMethodRef(Type type, short classIndex, short nameAndTypeIndex) {
super(type);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}//ConstantInterfaceMethodRef()//
/**
* Gets the constant pool index for the interface that defines the method (a ConstantType instance).
* @return The pool index of the class constant.
*/
public short getClassIndex() {
return classIndex;
}//getClassIndex()//
/**
* Gets the constant pool index for the name and type for the method (a ConstantNameAndType instance).
* @return The pool index of the name and type constant.
*/
public short getNameAndTypeIndex() {
return nameAndTypeIndex;
}//getNameAndTypeIndex()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantInterfaceMethodRef) && (((ConstantInterfaceMethodRef) object).classIndex == classIndex) && (((ConstantInterfaceMethodRef) object).nameAndTypeIndex == nameAndTypeIndex);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_INTERFACE_METHOD_REF;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (classIndex << 4) | nameAndTypeIndex;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
classIndex = in.readShort();
nameAndTypeIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant definingTypeConstant = getType().getConstant(classIndex);
Constant nameAndTypeConstant = getType().getConstant(nameAndTypeIndex);
Constant methodSignatureConstant = null;
Constant methodNameConstant = null;
if(definingTypeConstant instanceof ConstantType) {
definingTypeConstant = getType().getConstant(((ConstantType) definingTypeConstant).getNameIndex());
}//if//
if(definingTypeConstant instanceof ConstantString) {
definingTypeConstant = getType().getConstant(((ConstantString) definingTypeConstant).getStringIndex());
}//if//
if(nameAndTypeConstant instanceof ConstantNameAndType) {
methodNameConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getNameIndex());
methodSignatureConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getDescriptorIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodSignatureConstant instanceof ConstantString) {
methodSignatureConstant = getType().getConstant(((ConstantString) methodSignatureConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodNameConstant instanceof ConstantString) {
methodNameConstant = getType().getConstant(((ConstantString) methodNameConstant).getStringIndex());
}//if//
return definingTypeConstant instanceof ConstantUtf8 && methodNameConstant instanceof ConstantUtf8 && methodSignatureConstant instanceof ConstantUtf8 ? ((ConstantUtf8) definingTypeConstant).getValue() + "." + ((ConstantUtf8) methodNameConstant).getValue() + ((ConstantUtf8) methodSignatureConstant).getValue() + " (Interface Method Name)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Interface Method Reference (classIndex: " + classIndex + " nameAndTypeIndex: " + nameAndTypeIndex;
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Interface Method Reference Constant (classIndex=");
buffer.append(classIndex);
buffer.append(" nameAndTypeIndex=");
buffer.append(nameAndTypeIndex);
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex);
}//writeExternal()//
}//ConstantInterfaceMethodRef//

View File

@@ -0,0 +1,112 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantLong extends Constant {
private long value = 0;
/**
* ConstantLong constructor.
* @param type The class this constant is a member of.
*/
public ConstantLong(Type type) {
super(type);
}//ConstantLong()//
/**
* ConstantLong constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantLong(Type type, long value) {
super(type);
this.value = value;
}//ConstantLong()//
/**
* Gets the value for this associated with this constant.
* @return The long value.
*/
public long getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantLong) && (value == ((ConstantLong) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 8;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_LONG;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (int) value;
}//hashCode()//
/**
* Determines whether the constant takes double the constant entries in the class bytes.
* @return Whether the constant is a double size constant.
*/
public boolean isDoubleSize() {
return true;
}//isDoubleSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readLong();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Long.toString(value) + " (Long)";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Long: " + Long.toString(value);
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Long Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeLong(value);
}//writeExternal()//
}//ConstantLong//

View File

@@ -0,0 +1,142 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a method that is part of another class.
*/
public class ConstantMethodRef extends Constant {
/** The reference to the class that defines the method. */
private short classIndex = 0;
/** The reference to the name and signature of the method. */
private short nameAndTypeIndex = 0;
/**
* ConstantMethodRef constructor.
* @param type The class this constant is a member of.
*/
public ConstantMethodRef(Type type) {
super(type);
}//ConstantMethodRef()//
/**
* ConstantMethodRef constructor.
* @param type The class this constant is a member of.
* @param classIndex The index of the class constant.
* @param nameAndTypeIndex The index of the name and type descriptor constant.
*/
public ConstantMethodRef(Type type, short classIndex, short nameAndTypeIndex) {
super(type);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}//ConstantMethodRef()//
/**
* Gets the constant pool index for the class that defines the method (a ConstantType instance).
* @return The pool index of the class constant.
*/
public short getClassIndex() {
return classIndex;
}//getClassIndex()//
/**
* Gets the constant pool index for the name and type for the method (a ConstantNameAndType instance).
* @return The pool index of the name and type constant.
*/
public short getNameAndTypeIndex() {
return nameAndTypeIndex;
}//getNameAndTypeIndex()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public int getSize() {
return 4;
}//getSize()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getTag()
*/
public byte getTag() {
return CONSTANT_METHOD_REF;
}//getTag()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (classIndex << 4) | nameAndTypeIndex;
}//hashCode()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof ConstantMethodRef) && (((ConstantMethodRef) object).classIndex == classIndex) && (((ConstantMethodRef) object).nameAndTypeIndex == nameAndTypeIndex);
}//equals()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
classIndex = in.readShort();
nameAndTypeIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex);
}//writeExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant definingTypeConstant = getType().getConstant(classIndex);
Constant nameAndTypeConstant = getType().getConstant(nameAndTypeIndex);
Constant methodSignatureConstant = null;
Constant methodNameConstant = null;
if(definingTypeConstant instanceof ConstantType) {
definingTypeConstant = getType().getConstant(((ConstantType) definingTypeConstant).getNameIndex());
}//if//
if(definingTypeConstant instanceof ConstantString) {
definingTypeConstant = getType().getConstant(((ConstantString) definingTypeConstant).getStringIndex());
}//if//
if(nameAndTypeConstant instanceof ConstantNameAndType) {
methodNameConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getNameIndex());
methodSignatureConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getDescriptorIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodSignatureConstant instanceof ConstantString) {
methodSignatureConstant = getType().getConstant(((ConstantString) methodSignatureConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodNameConstant instanceof ConstantString) {
methodNameConstant = getType().getConstant(((ConstantString) methodNameConstant).getStringIndex());
}//if//
return definingTypeConstant instanceof ConstantUtf8 && methodNameConstant instanceof ConstantUtf8 && methodSignatureConstant instanceof ConstantUtf8 ? ((ConstantUtf8) definingTypeConstant).getValue() + "." + ((ConstantUtf8) methodNameConstant).getValue() + ((ConstantUtf8) methodSignatureConstant).getValue() + " (Method Name)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "Method Reference (classIndex: " + classIndex + " nameAndTypeIndex: " + nameAndTypeIndex;
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Component#toString(java.lang.StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Method Reference Constant (classIndex=");
buffer.append(classIndex);
buffer.append(" nameAndTypeIndex=");
buffer.append(nameAndTypeIndex);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
}//ConstantMethodRef//

View File

@@ -0,0 +1,138 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a method or field name and signature (descriptor).
*/
public class ConstantNameAndType extends Constant {
/** The index of the name of the method (ie: 'parseInt'). */
private short nameIndex = 0;
/** The index of the method or field descriptor (ie: '(Ljava/lang/String;)I' or for a field: 'Ljava/lang/String;' without quotes of course). */
private short descriptorIndex = 0;
/**
* ConstantNameAndType constructor.
* @param type The class this constant is a member of.
*/
public ConstantNameAndType(Type type) {
super(type);
}//ConstantNameAndType()//
/**
* ConstantNameAndType constructor.
* @param type The class this constant is a member of.
* @param nameIndex The index of the name constant.
* @param descriptorIndex The descriptor constant index.
*/
public ConstantNameAndType(Type type, short nameIndex, short descriptorIndex) {
super(type);
this.nameIndex = nameIndex;
this.descriptorIndex = descriptorIndex;
}//ConstantNameAndType()//
/**
* Gets the constant pool index for the name.
* @return The index in the type's constant pool for the name which should be a ConstantUtf8.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/**
* Gets the constant pool index for the descriptor.
* @return The index in the type's constant pool for the descriptor.
*/
public short getDescriptorIndex() {
return descriptorIndex;
}//getDescriptorIndex()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (nameIndex << 4) | descriptorIndex;
}//hashCode()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof ConstantNameAndType) && (((ConstantNameAndType) object).nameIndex == nameIndex) && (((ConstantNameAndType) object).descriptorIndex == descriptorIndex);
}//equals()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public int getSize() {
return 4;
}//getSize()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getTag()
*/
public byte getTag() {
return CONSTANT_NAME_AND_TYPE;
}//getTag()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
nameIndex = in.readShort();
descriptorIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(nameIndex);
out.writeShort(descriptorIndex);
}//writeExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant fieldTypeConstant = getType().getConstant(getDescriptorIndex());
Constant fieldNameConstant = getType().getConstant(getNameIndex());
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantType) {
fieldTypeConstant = getType().getConstant(((ConstantType) fieldTypeConstant).getNameIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantString) {
fieldTypeConstant = getType().getConstant(((ConstantString) fieldTypeConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldNameConstant instanceof ConstantString) {
fieldNameConstant = getType().getConstant(((ConstantString) fieldNameConstant).getStringIndex());
}//if//
return fieldTypeConstant instanceof ConstantUtf8 && fieldNameConstant instanceof ConstantUtf8 ? ((ConstantUtf8) fieldTypeConstant).getValue() + " " + ((ConstantUtf8) fieldNameConstant).getValue() + " (Name & Type)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
Constant descriptorConstant = getType().getConstant(descriptorIndex);
Constant nameConstant = getType().getConstant(nameIndex);
return "Descriptor: " + (descriptorConstant instanceof ConstantNameAndType ? (" DescriptorIndex: " + descriptorIndex + "<--ERROR") : descriptorConstant.toString()) + (nameConstant instanceof ConstantNameAndType ? (" NameIndex: " + nameIndex + "<--ERROR") : (" Name: " + getType().getConstant(nameIndex)));
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Component#toString(java.lang.StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Name & Type Constant (nameIndex=");
buffer.append(nameIndex);
buffer.append(" descriptorIndex=");
buffer.append(descriptorIndex);
buffer.append(" value='");
buffer.append(toString());
buffer.append('\'');
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
}//ConstantNameAndType//

View File

@@ -0,0 +1,110 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* References a string in the constant pool.
*/
public class ConstantString extends Constant {
private short stringIndex = 0;
/**
* ConstantString constructor.
* @param type The class this constant is a member of.
*/
public ConstantString(Type type) {
super(type);
}//ConstantString()//
/**
* ConstantString constructor.
* @param type The class this constant is a member of.
*/
public ConstantString(Type type, short stringIndex) {
super(type);
this.stringIndex = stringIndex;
}//ConstantString()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantString) && (((ConstantString) object).stringIndex == stringIndex);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2;
}//getSize()//
/**
* Gets the constant pool index of the string which should be a ConstantUtf8 object.
* @return The index in the constant pool of the actual string.
*/
public short getStringIndex() {
return stringIndex;
}//getStringIndex()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_STRING;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return stringIndex;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
stringIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant constant = getType().getConstant(stringIndex);
return constant instanceof ConstantUtf8 ? "\"" + ((ConstantUtf8) constant).getValue().replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replace("\t", "\\\\t") + "\" (String w/o Quotes)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "String" + (getType().getConstant(stringIndex) instanceof ConstantString ? " Index: " + stringIndex + " <--ERROR" : ": " + getType().getConstant(stringIndex));
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("String Constant (index=");
buffer.append(stringIndex);
buffer.append(" value='");
buffer.append(getType().getConstant(stringIndex).toString());
buffer.append('\'');
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(stringIndex);
}//writeExternal()//
}//ConstantString//

View File

@@ -0,0 +1,106 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a class name constant.
*/
public class ConstantType extends Constant {
/** The index of the class name (ie: 'com/common/util/LiteList'). */
private short nameIndex = 0;
/**
* ConstantType constructor.
*/
public ConstantType(Type type) {
super(type);
}//ConstantType()//
/**
* ConstantType constructor.
* @param type The class this constant is a member of. <b>Warning: This type must be in the class file format for class names.</b>
*/
public ConstantType(Type type, short nameIndex) {
super(type);
this.nameIndex = nameIndex;
}//ConstantType()//
/**
* Gets the class name's index within the type's constant pool.
* @return The constant pool index of the class name.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public int getSize() {
return 2;
}//getSize()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getTag()
*/
public byte getTag() {
return CONSTANT_CLASS;
}//getTag()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return nameIndex;
}//hashCode()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof ConstantType) && (((ConstantType) object).nameIndex == nameIndex);
}//equals()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
nameIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(nameIndex);
}//writeExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant constant = getType().getConstant(nameIndex);
if(constant instanceof ConstantString) {
constant = getType().getConstant(((ConstantString) constant).getStringIndex());
}//if//
return constant instanceof ConstantUtf8 ? "\"" + ((ConstantUtf8) constant).getValue() + "\" (Type w/o Quotes)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return getType().getConstant(nameIndex) instanceof ConstantType ? "NameIndex: " + nameIndex + " <--ERROR" : "Name: " + getType().getConstant(nameIndex);
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Component#toString(java.lang.StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Class Constant (index=");
buffer.append(nameIndex);
buffer.append(" value='");
buffer.append(getType().getConstant(nameIndex).toString());
buffer.append('\'');
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
}//ConstantType//

View File

@@ -0,0 +1,154 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.common.debug.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantUtf8 extends Constant {
private static final String UTF8_ENCODING = "UTF8";
private byte[] bytes = null;
private String value = null;
/**
* ConstantUtf8 constructor.
* @param type The class this constant is a member of.
*/
public ConstantUtf8(Type type) {
super(type);
}//ConstantUtf8()//
/**
* ConstantUtf8 constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantUtf8(Type type, String value) {
super(type);
setValue(value);
}//ConstantUtf8()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantUtf8) && (((((ConstantUtf8) object).getValue() == null) && (getValue() == null)) || ((((ConstantUtf8) object).getValue() != null) && ((ConstantUtf8) object).getValue().equals(getValue())));
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return getValueBytes().length + 2;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_UTF8;
}//getTag()//
/**
* Gets the value for this associated with this constant.
* @return The string value.
*/
public String getValue() {
return value;
}//getValue()//
/**
* Gets the byte array value for the string. The bytes will be created if they have not yet.
* @return The string value as a byte array.
*/
public byte[] getValueBytes() {
if(bytes == null) {
try {
bytes = value.getBytes(UTF8_ENCODING);
}//try//
catch(java.io.UnsupportedEncodingException e) {
Debug.log(e);
Debug.halt();
}//catch//
}//if//
return bytes;
}//getValueBytes()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return value != null ? value.hashCode() : 0;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
int readCount = 0;
int size = (((int) (((byte) in.read()) & 0xFF) << 8) + ((int) (((byte) in.read()) & 0xFF)));
bytes = new byte[size];
while(readCount != bytes.length) {
readCount += in.read(bytes, readCount, bytes.length - readCount);
}//while//
convertToString(bytes);
}//readExternal()//
/**
* Converts the bytes into a UTF8 string.
* <p>Note: This method was created to house this one line of code due to a VM error or compiler error in JDK 1.5_08. For some strange reason separating the line allows the app to not crash and a correct value to be returned.</p>
* @param bytes
* @throws IOException
* @throws ClassNotFoundException
*/
private void convertToString(byte[] bytes) throws IOException, ClassNotFoundException {
value = new String(bytes, UTF8_ENCODING);
}//convertToString()//
/**
* Sets the value for this associated with this constant.
* @param value The string value.
*/
public void setValue(String value) {
this.value = value;
this.bytes = null;
}//getValue()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return "\"" + value.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\t", "\\\\t") + "\" (UTF8 w/o Quotes)";
}//getPrettyValue()//
/**
* Provides a debug output string representing this object.
* @return A debug string representing this object.
*/
public String toString() {
return value.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\t", "\\\\t");
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("UTF8 Constant (");
buffer.append(value.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\t", "\\\\t"));
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort((short) getValueBytes().length);
out.write(getValueBytes());
}//writeExternal()//
}//ConstantUtf8//

View File

@@ -0,0 +1,205 @@
package com.de22.javabytecode.generator;
import java.io.IOException;
import java.lang.reflect.Modifier;
import com.common.io.*;
import com.common.debug.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.code.*;
/**
* Copyright Declarative Engineering LLC 1999<p>
* Provides some assistance methods for generating a class.
*/
public abstract class ClassGenerator {
public static final String INIT_METHOD_NAME = "<init>";
//private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
protected StringBuffer sharedBuffer = new StringBuffer(500); //A shared string buffer that can be used by the class generator and subclasses to temporarily buffer data within the method. Warning: This is reused by many methods so make sure you don't store anything important before calling another method.//
private Type type = null;
/**
* ClassGenerator constructor.
*/
private ClassGenerator() {
super();
}//ClassGenerator()//
/**
* ClassGenerator constructor.
*/
public ClassGenerator(String qualifiedClassName) {
super();
createClass(qualifiedClassName);
}//ClassGenerator()//
/**
* Creates a new type. All subsequent operations are against this type.
* <p>TODO: Provide more input to this method to allow different access flags and such.
* @param qualifiedClassName The fully qualified class name of this new class. Must use '/' instead of '.' & do not use a '.class' or '.java' extention.
*/
protected void createClass(String qualifiedClassName) {
try {
Type type = new Type(qualifiedClassName);
type.setAccessFlags((short) (Type.ACC_PUBLIC | Type.ACC_SUPER));
type.setMajorVersion((short) 45);
type.setMinorVersion((short) 3);
setType(type);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//createClass()//
/**
* Creates the one and only init method which should at the very least call the super classes' init method.
* <p>TODO: Stop ignoring the passed byte codes and instead add them in the mix.
* @param superClass The class that this class will inherit from.
* @param code This parameter is currently ignored.
*/
public void createInitMethod(Class superClass, byte[] code) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream(20, false);
StandardOutputStream out = new StandardOutputStream(bout);
short superInitIndex = getType().addConstantMethod(superClass, null, INIT_METHOD_NAME, new Class[0]);
out.writeByte((byte) 42); //aload_0
out.writeByte((byte) 183); //invokespecial -> invoke super class' <init> method.
out.writeShort((short) superInitIndex);
out.writeByte((byte) 177); //return
//Add the method to the type.//
getType().addMethod(Modifier.PUBLIC, null, INIT_METHOD_NAME, new Class[0], bout.toByteArray(), 1, 1);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//createInitMethod()//
/**
* Formats a descriptor string using the parameters and return type of the method.
* This is used to create method descriptors for a class file.
* <p>Example: void methodName(double[] a, String b) -> ([DLjava/lang/String;)V;
* @param returnType The descriptor's return type.
* @param parameterTypes The descriptor's parameter types (in order of parameter).
* @return The formatted type string.
*/
protected String formatDescriptor(Class returnType, Class[] parameterTypes) {
sharedBuffer.setLength(0);
FormatSupport.formatDescriptor(returnType, parameterTypes, sharedBuffer);
return sharedBuffer.toString();
}//formatDescriptor()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type The non-primitive class to convert to a string.
* @return The string representation of the type.
*/
protected String formatNonPrimitiveType(String qualifiedTypeName) {
sharedBuffer.setLength(0);
FormatSupport.formatNonPrimitiveType(qualifiedTypeName, sharedBuffer);
return sharedBuffer.toString();
}//formatNonPrimitiveType()//
/**
* Formats a class to a class file compatible string.
* @param type The class to convert to a string.
* @return The formatted type string.
*/
protected String formatType(Class type) {
sharedBuffer.setLength(0);
FormatSupport.formatType(type, sharedBuffer);
return sharedBuffer.toString();
}//formatType()//
/**
* Generates a method signature string from the method.
* @param method The method whose signature should be generated.
*/
protected static String generateMethodSignature(java.lang.reflect.Method method) {
try {
StringBuffer signature = new StringBuffer(100);
Class[] parameterTypes = method.getParameterTypes();
for(int index = 0; index < parameterTypes.length; index++) {
if(signature == null) {
signature = new StringBuffer(100);
}//if//
else {
signature.append(',');
signature.append(' ');
}//else//
signature.append(parameterTypes[index].getName());
}//for//
signature.append('(');
if(signature != null) {
signature.append(signature);
}//if//
signature.append(')');
return signature.toString();
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
return "";
}//catch//
}//generateMethodSignature()//
/**
* Gets the classes' byte codes.
* @return The array of byte codes for the class.
*/
public byte[] getClassByteCodes() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1000, false);
getType().writeExternal(new ObjectOutputStream(out, null));
return out.toByteArray();
}//getClassByteCodes()//
/**
* Gets the classes' type object.
* @return The type object describing the class byte codes.
*/
public Type getType() {
return type;
}//getType()//
/**
* Sets the classes' source file reference.
* <p>TODO: Implement this properly by adding an addAttributeSourceFile method to the Type class.
* @param path The path to the source file that created this class.
*/
public void setSourceFile(String path) {
try {
//Type type = getType();
//SourceFile sourceFile = new SourceFile(type, path);
//Add the attribute to the class.//
//type.addAttribute(sourceFile);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//setSuperClass()//
/**
* Sets the super class for this class.
* @param qualifiedSuperClassName The qualified class name of the super class. This string will be reformatted for use in the class byte codes.
*/
public void setSuperClass(String qualifiedSuperClassName) {
Type type = getType();
type.setSuperClass(formatNonPrimitiveType(qualifiedSuperClassName));
}//setSuperClass()//
/**
* Sets the classes' type object.
* @param type The type object describing the class byte codes.
*/
private void setType(Type type) {
this.type = type;
}//setType()//
}//ClassGenerator//

View File

@@ -0,0 +1,54 @@
package com.de22.javabytecode.io;
import java.io.IOException;
import com.common.io.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ByteCodeOutputStream extends StandardOutputStream {
/**
* ByteCodeOutputStream constructor.
* The size of the initial buffer in bytes.
*/
public ByteCodeOutputStream(int bufferSize) {
super(new BufferedOutputStream(new ByteArrayOutputStream(bufferSize, false)));
}//ByteCodeOutputStream()//
/**
* ByteCodeOutputStream constructor.
* @param outputStream The buffered output stream to wrapper.
*/
protected ByteCodeOutputStream(BufferedOutputStream outputStream) {
super(outputStream);
}//ByteCodeOutputStream()//
/**
* @see BufferedOutputStream.getByteIndex()
*/
public int getByteIndex() {
return ((BufferedOutputStream) getOutputStream()).getByteIndex();
}//getByteIndex()//
/**
* @see BufferedOutputStream.getInsertOutputStream(int)
*/
public ByteCodeOutputStream getInsertOutputStream(int reservedByteCount) throws IOException {
return new ByteCodeOutputStream(((BufferedOutputStream) getOutputStream()).getInsertOutputStream(reservedByteCount));
}//getInsertOutputStream()//
/**
* @see BufferedOutputStream.getInsertOutputStream(int, int)
*/
public ByteCodeOutputStream getInsertOutputStream(int bufferSize, int incrementSize) throws IOException {
return new ByteCodeOutputStream(((BufferedOutputStream) getOutputStream()).getInsertOutputStream(bufferSize, incrementSize));
}//getInsertOutputStream()//
/**
* @see BufferedOutputStream.getOutputStreamLocation()
*/
public IOutputStreamLocation getOutputStreamLocation() throws IOException {
return ((BufferedOutputStream) getOutputStream()).getOutputStreamLocation();
}//getOutputStreamLocation()//
/**
* @see ByteArrayOutputStream.toByteArray()
*/
public byte[] toByteArray() throws IOException {
return ((BufferedOutputStream) getOutputStream()).toByteArray();
}//toByteArray()//
}//ByteCodeOutputStream//

View File

@@ -0,0 +1,115 @@
package com.de22.javabytecode.util;
import com.common.debug.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Assists the code in tracking the stack size at any given time, and the total stack size of a segment of code.
*/
public class StackTracker {
private int stackSize = 0; //The current stack size of the code segment.//
private int maxStackSize = 0; //The maximum stack size of the code segment.//
/**
* StackTracker constructor.
*/
public StackTracker() {
super();
}//StackTracker()//
/**
* StackTracker constructor.
*/
protected StackTracker(int stackSize, int maxStackSize) {
super();
this.stackSize = stackSize;
this.maxStackSize = maxStackSize;
}//StackTracker()//
/**
* Derements the stack size by one.
*/
public void decrement() {
stackSize--;
}//decrement()//
/**
* Derements the stack size by <code>count</code>.
* @param count The count by which the stack should be decremented.
*/
public void decrement(int count) {
stackSize -= count;
}//decrement()//
/**
* Gets the maximum size of the stack at any point in the code segment.
* @return The maximum size the stack took durring its life.
*/
public int getMaxStackSize() {
return maxStackSize;
}//getMaxStackSize()//
/**
* Gets the current stack size.
* @return The size of the stack at the current point in the code.
*/
public int getStackSize() {
return stackSize;
}//getStackSize()//
/**
* Increments the stack size by one.
*/
public void increment() {
stackSize++;
if(maxStackSize < stackSize) {
maxStackSize = stackSize;
}//if//
}//increment()//
/**
* Increments the stack size by <code>count</code>.
* @param count The count by which the stack should be incremented.
*/
public void increment(int count) {
stackSize += count;
if(maxStackSize < stackSize) {
maxStackSize = stackSize;
}//if//
}//increment()//
/**
* Merges the stack trackers into one.
* This is useful when the code branches at it is necessary to merge two separate branches of the code.
* <p>Important: The stack trackers must have the same stack size in order to be merged! A runtime exception will ensue if they are not equal.
* @param stackTracker The stack tracker to merge with this stack tracker. The passed stack tracker will not be affected.
*/
public void merge(StackTracker stackTracker) {
//Ensure that both stacks have the same size.//
if(stackTracker.stackSize != stackSize) {
Debug.halt();
throw new RuntimeException("Critical Error: Unable to merge the stack data.");
}//if//
//Set the greater of the two maximum stack size values.//
if(stackTracker.maxStackSize > maxStackSize) {
maxStackSize = stackTracker.maxStackSize;
}//if//
}//merge()//
/**
* Resets the tracker counts.
*/
public void reset() {
stackSize = 0;
maxStackSize = 0;
}//reset()//
/**
* Splits the stack tracker into two.
* This is useful when the code branches at it is necessary to track two separate branches of the code.
* @return A duplicate stack tracker.
*/
public StackTracker split() {
return new StackTracker(stackSize, maxStackSize);
}//split()//
/**
* Gets a debug string for the stack tracker.
* @return A string representing the current state of the stack tracker.
*/
public String toString() {
return "StackTracker[stackSize = " + stackSize + ", maxStackSize = " + maxStackSize + "]";
}//toString()//
}//StackTracker//