diff --git a/jode/jode/bytecode/BasicBlockReader.java b/jode/jode/bytecode/BasicBlockReader.java index 24ab8da..80af89c 100644 --- a/jode/jode/bytecode/BasicBlockReader.java +++ b/jode/jode/bytecode/BasicBlockReader.java @@ -256,7 +256,7 @@ class BasicBlockReader implements Opcodes { if (!alwaysJump) succs[succLength] = getSuccBlock(info.nextAddr); - blocks[blockNr].setCode(Arrays.asList(instrs), succs); + blocks[blockNr].setCode(instrs, succs); } void convert() throws ClassFormatException { @@ -331,7 +331,9 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); - instr = new SlotInstruction(wideopcode, slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); + instr = new SlotInstruction(wideopcode, lvi); length = 4; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -345,7 +347,9 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals-1) throw new ClassFormatException ("Invalid local slot "+slot); - instr = new SlotInstruction(wideopcode, slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); + instr = new SlotInstruction(wideopcode, lvi); length = 4; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -358,7 +362,9 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); - instr = new SlotInstruction(wideopcode, slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); + instr = new SlotInstruction(wideopcode, lvi); length = 4; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -370,8 +376,10 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); int incr = input.readShort(); - instr = new IncInstruction(wideopcode, slot, incr); + instr = new IncInstruction(wideopcode, lvi, incr); length = 6; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -399,8 +407,10 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); instr = new SlotInstruction - (opc_iload + (opcode-opc_iload_0)/4, slot); + (opc_iload + (opcode-opc_iload_0)/4, lvi); length = 1; break; } @@ -414,8 +424,10 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); instr = new SlotInstruction - (opc_istore + (opcode-opc_istore_0)/4, slot); + (opc_istore + (opcode-opc_istore_0)/4, lvi); length = 1; break; } @@ -427,8 +439,10 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals-1) throw new ClassFormatException ("Invalid local slot "+slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); instr = new SlotInstruction - (opc_lstore + (opcode-opc_lstore_0)/4, slot); + (opc_lstore + (opcode-opc_lstore_0)/4, lvi); length = 1; break; } @@ -438,7 +452,9 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); - instr = new SlotInstruction(opcode, slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); + instr = new SlotInstruction(opcode, lvi); length = 2; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -451,7 +467,9 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals - 1) throw new ClassFormatException ("Invalid local slot "+slot); - instr = new SlotInstruction(opcode, slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); + instr = new SlotInstruction(opcode, lvi); length = 2; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -463,7 +481,9 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); - instr = new SlotInstruction(opcode, slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); + instr = new SlotInstruction(opcode, lvi); length = 2; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -535,8 +555,10 @@ class BasicBlockReader implements Opcodes { if (slot >= maxLocals) throw new ClassFormatException ("Invalid local slot "+slot); + LocalVariableInfo lvi + = LocalVariableInfo.getInfo(slot); int incr = input.readByte(); - instr = new IncInstruction(opcode, slot, incr); + instr = new IncInstruction(opcode, lvi, incr); length = 3; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_BYTECODE) != 0) @@ -958,3 +980,4 @@ class BasicBlockReader implements Opcodes { } } } + diff --git a/jode/jode/bytecode/BasicBlockWriter.java b/jode/jode/bytecode/BasicBlockWriter.java index 5f3198e..780c80c 100644 --- a/jode/jode/bytecode/BasicBlockWriter.java +++ b/jode/jode/bytecode/BasicBlockWriter.java @@ -89,11 +89,10 @@ class BasicBlockWriter implements Opcodes { int blockNr = block.getBlockNr(); LocalVariableInfo[] life = (LocalVariableInfo[]) atStart[blockNr].clone(); - for (Iterator iter = block.getInstructions().iterator(); - iter.hasNext() ; ) { - Instruction instr = (Instruction) iter.next(); - if (instr.hasLocal()) { - LocalVariableInfo lvi = instr.getLocalInfo(); + Instruction[] instrs = block.getInstructions(); + for (int i = 0; i < instrs.length; i++) { + if (instrs[i].hasLocal()) { + LocalVariableInfo lvi = instrs[i].getLocalInfo(); int slot = lvi.getSlot(); if (life[slot] != null && life[slot] != lvi) @@ -162,10 +161,9 @@ class BasicBlockWriter implements Opcodes { } } - int size = block.getInstructions().size(); - for (int k = 0; k < size; k++) { - Instruction instr - = (Instruction) block.getInstructions().get(k); + Instruction[] instrs = block.getInstructions(); + for (int k = 0; k < instrs.length; k++) { + Instruction instr = instrs[k]; if (instr.hasLocal()) { LocalVariableInfo lvi = instr.getLocalInfo(); int slot = lvi.getSlot(); @@ -227,12 +225,11 @@ class BasicBlockWriter implements Opcodes { next_block: for (int i = 0; i < blocks.length; i++) { blockAddr[i] = addr; - List instructions = blocks[i].getInstructions(); - int size = instructions.size(); - instrLength[i] = new int[size]; + Instruction[] instrs = blocks[i].getInstructions(); + instrLength[i] = new int[instrs.length]; Block[] succs = blocks[i].getSuccs(); - for (int j = 0; j < size; j++) { - Instruction instr = (Instruction) instructions.get(j); + for (int j = 0; j < instrs.length; j++) { + Instruction instr = instrs[j]; if (instr.hasLineNr()) lntCount++; @@ -637,10 +634,10 @@ class BasicBlockWriter implements Opcodes { Block[] succs = blocks[i].getSuccs(); if (addr != blockAddr[i]) throw new InternalError("Address calculation broken!"); - List instructions = blocks[i].getInstructions(); - int size = instructions.size(); + Instruction[] instructions = blocks[i].getInstructions(); + int size = instructions.length; for (int j = 0; j < size; j++) { - Instruction instr = (Instruction) instructions.get(j); + Instruction instr = instructions[j]; if (instr.hasLineNr()) { lnt[lntPtr++] = (short) addr; lnt[lntPtr++] = (short) instr.getLineNr(); diff --git a/jode/jode/bytecode/BasicBlocks.java b/jode/jode/bytecode/BasicBlocks.java index ad7464b..6e8db2e 100644 --- a/jode/jode/bytecode/BasicBlocks.java +++ b/jode/jode/bytecode/BasicBlocks.java @@ -1,4 +1,4 @@ -/* BasicBlocks Copyright (C) 1999 Jochen Hoenicke. +/* BasicBlocks Copyright (C) 2000 Jochen Hoenicke. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ import java.io.PrintWriter; ///#def COLLECTIONS java.util import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; ///#enddef @@ -36,22 +37,37 @@ import java.lang.UnsupportedOperationException; ///#enddef /** - *

This class gives another representation of the byte code of a - * method. The instructions are splitted into BasicBlocks, each an - * array of consecutive Instructions. It is not allowed that a goto - * jumps inside a basic block.

+ *

Represents the byte code of a method in form of basic blocks. A + * basic block is a bunch of instructions, that must always execute in + * sequential order. Every basic block is represented by an Block + * object.

* - *

All jumps must be at the end of the block. A conditional jump - * may be followed by a single goto, but there must not be any other - * jumps. If there is now unconditional jump at the end, the block - * implicitely flows into the next one.

+ *

All jump instructions must be at the end of the block, and the + * jump instructions doesn't have to remember where they jump to. + * Instead this information is stored inside the blocks. See + * Block for details.

* - *

Try block must span over some consecutive BasicBlocks and there - * catches must jump to the start of an basic block.

+ *

A subroutine block, i.e. a block where some jsr instructions may + * jump to, must store its return address in a local variable + * immediately. There must be exactly one block with the + * corresponding opc_ret instruction and all blocks that + * belong to this subroutine must point to the ret block. Bytecode + * that doesn't have this condition is automatically transformed on + * reading.

* - *

Deadcode will not be included in the BasicBlock, also - * BasicBlocks consisting of a single jump will be optimized away.

+ *

Exception Handlers are represented by the Handler class. Their + * start/end range must span over some consecutive BasicBlocks and + * there handler must be another basic block.

* + *

If you want to create or modify the byte code, you must first set + * the basic blocks and then set exception handlers. If you set new + * blocks the previous exception handlers will be removed.

+ * + *

When the code is written to a class file, the blocks are written + * in the given order. Goto and return instructions are inserted as + * necessary, you don't have to care about that.

+ * + * @see jode.bytecode.Block * @see jode.bytecode.Instruction */ public class BasicBlocks extends BinaryInfo { @@ -121,39 +137,6 @@ public class BasicBlocks extends BinaryInfo { return blocks; } - public Iterator getAllInstructions() { - return new Iterator() { - int blockNr = 0; - Iterator blockIter = getNextIterator(); - - public boolean hasNext() { - return blockIter != null; - } - - public Iterator getNextIterator() { - if (blockNr < blocks.length) - return blocks[blockNr++].getInstructions().iterator(); - return null; - } - - public Object next() { - Object instr; - try { - instr = blockIter.next(); - } catch (NullPointerException ex) { - throw new NoSuchElementException(); - } - if (!blockIter.hasNext()) - blockIter = getNextIterator(); - return instr; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - /** * @return the exception handlers, or null if the method has no * exception handlers. @@ -215,7 +198,7 @@ public class BasicBlocks extends BinaryInfo { } private BasicBlockReader reader; - public void read(ConstantPool cp, + void read(ConstantPool cp, DataInputStream input, int howMuch) throws IOException { if ((GlobalOptions.debuggingFlags @@ -231,7 +214,7 @@ public class BasicBlocks extends BinaryInfo { dumpCode(GlobalOptions.err); } - protected void readAttribute(String name, int length, ConstantPool cp, + void readAttribute(String name, int length, ConstantPool cp, DataInputStream input, int howMuch) throws IOException { if (howMuch >= ClassInfo.ALMOSTALL @@ -248,7 +231,8 @@ public class BasicBlocks extends BinaryInfo { void reserveSmallConstants(GrowableConstantPool gcp) { for (int i=0; i < blocks.length; i++) { next_instr: - for (Iterator iter = blocks[i].getInstructions().iterator(); + for (Iterator iter + = Arrays.asList(blocks[i].getInstructions()).iterator(); iter.hasNext(); ) { Instruction instr = (Instruction) iter.next(); if (instr.getOpcode() == Opcodes.opc_ldc) { @@ -293,7 +277,7 @@ public class BasicBlocks extends BinaryInfo { writeAttributes(gcp, output); bbw = null; } - + public void dumpCode(PrintWriter output) { output.println(methodInfo.getName()+methodInfo.getType()+":"); if (startBlock == null) diff --git a/jode/jode/bytecode/BinaryInfo.java b/jode/jode/bytecode/BinaryInfo.java index a2d3e44..c808232 100644 --- a/jode/jode/bytecode/BinaryInfo.java +++ b/jode/jode/bytecode/BinaryInfo.java @@ -34,10 +34,26 @@ import java.util.Iterator; /** + *

Represents a container for user specified attributes.

* - * @author Jochen Hoenicke + *

Java bytecode is extensible: Classes, Methods and Fields may + * have any number of attributes. Every attribute has a name and some + * unformatted data.

+ * + *

There are some predefined attributes, even the Code of a Method + * is an attribute. These predefined attributes are all handled by + * this package as appropriate. This methods are only useful for non + * standard attributes.

+ * + *

One application of this attributes are installation classes. + * These classes have a special attribute containing a zip of the + * files that should be installed. There are other possible uses, + * e.g. putting native machine code for some architectures into the + * class.

+ * + * @author Jochen Hoenicke */ -class BinaryInfo { +public class BinaryInfo { private Map unknownAttributes = null; void skipAttributes(DataInputStream input) throws IOException { @@ -140,8 +156,9 @@ class BinaryInfo { } } - public void dropAttributes() { - unknownAttributes = null; + void drop(int keep) { + if (keep < ClassInfo.ALL) + unknownAttributes = null; } void prepareAttributes(GrowableConstantPool gcp) { @@ -178,7 +195,7 @@ class BinaryInfo { } } - public int getAttributeSize() { + int getAttributeSize() { int size = 2; /* attribute count */ if (unknownAttributes != null) { Iterator i = unknownAttributes.values().iterator(); @@ -188,31 +205,55 @@ class BinaryInfo { return size; } + /** + * Finds a non standard attribute with the given name. + * @param name the name of the attribute. + * @return the contents of the attribute, null if not found. + */ public byte[] findAttribute(String name) { if (unknownAttributes != null) return (byte[]) unknownAttributes.get(name); return null; } + /** + * Gets all non standard attributes + */ public Iterator getAttributes() { if (unknownAttributes != null) return unknownAttributes.values().iterator(); return Collections.EMPTY_SET.iterator(); } - public void setAttribute(String name, byte[] content) { + /** + * Adds a new non standard attribute or replaces an old one with the + * same name. + * @param name the name of the attribute. + * @param contents the new contens. + */ + public void setAttribute(String name, byte[] contents) { if (unknownAttributes == null) unknownAttributes = new SimpleMap(); - unknownAttributes.put(name, content); + unknownAttributes.put(name, contents); } + /** + * Removes a new non standard attribute. + * @param name the name of the attribute. + * @return the old contents of the attribute. + */ public byte[] removeAttribute(String name) { if (unknownAttributes != null) return (byte[]) unknownAttributes.remove(name); return null; } + /** + * Removes all non standard attribute. + */ public void removeAllAttributes() { unknownAttributes = null; } } + + diff --git a/jode/jode/bytecode/Block.java b/jode/jode/bytecode/Block.java index 2ebb456..3e4dd20 100644 --- a/jode/jode/bytecode/Block.java +++ b/jode/jode/bytecode/Block.java @@ -1,4 +1,4 @@ -/* Block Copyright (C) 1999 Jochen Hoenicke. +/* Block Copyright (C) 2000 Jochen Hoenicke. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,12 +28,48 @@ import java.util.Iterator; ///#enddef /** - * Represents a single basic block. It contains a list of - * instructions, the successor blocks and the exception handlers for - * this block. The last Instruction, and only the last, may be a - * conditional jump, a tableswitch or a jsr. + *

Represents a single basic block. It contains a list of + * instructions and the successor blocks.

* - * @author Jochen Hoenicke */ + *

All jump instructions must be at the end of the block. These + * jump instructions are opc_lookupswitch, + * opc_ifxxx, opc_jsr, opc_ret, + * opc_xreturn and opc_return. + * An opc_goto is implicit if the basic block doesn't end + * with a jump instructions, or if it ends with an conditional jump or + * jsr.

+ * + *

The jump instructions don't remember their destinations, instead + * the Block does it. This are the successor block. There are + * several cases:

+ * + * + * + *

If any successor is null it represents end of + * method, i.e. a return instruction. You can also use + * null successors for conditional jumps and switch + * instruction. You normally shouldn't use opc_return + * instructions. They are only necessary, if you want to return with + * a non-empty stack.

+ * + * @author Jochen Hoenicke + * @see jode.bytecode.BasicBlocks + * @see jode.bytecode.Instruction + */ public final class Block { /** * The opcodes of the instructions in this block. @@ -55,6 +91,21 @@ public final class Block { */ int blockNr; + /** + * The blockNr of this block. Set by BasicBlocks. + */ + int lineNr; + + /** + * The number of items this block takes from the stack. + */ + int pop; + /** + * The number of items this block puts on the stack. + */ + int push; + + /** * Creates a new empty block, with a null successor array. */ @@ -68,8 +119,8 @@ public final class Block { * modified, except that the instructions (but not their opcodes) * may be modified. */ - public List getInstructions() { - return Arrays.asList(instrs); + public Instruction[] getInstructions() { + return instrs; } /** @@ -105,35 +156,45 @@ public final class Block { return blockNr; } - private void checkConsistent() { - /* Check if all instructions are of correct type */ + private void initCode() { int size = instrs.length; + int depth = 0; + int poppush[] = new int[2]; + boolean needGoto = true; for (int i = 0; i < size; i++) { + instrs[i].getStackPopPush(poppush); + depth += poppush[0]; + if (pop < depth) + pop = depth; + depth -= poppush[1]; + int opcode = instrs[i].getOpcode(); switch (opcode) { case Opcodes.opc_goto: throw new IllegalArgumentException("goto in block"); case Opcodes.opc_lookupswitch: - if (succs == null || succs.length == 0) + if (succs.length != instrs[i].getValues().length + 1) throw new IllegalArgumentException ("no successors for switch"); if (i != size - 1) throw new IllegalArgumentException ("switch in the middle!"); - return; + needGoto = false; + break; case Opcodes.opc_ret: case Opcodes.opc_athrow: case Opcodes.opc_ireturn: case Opcodes.opc_lreturn: case Opcodes.opc_freturn: case Opcodes.opc_dreturn: case Opcodes.opc_areturn: case Opcodes.opc_return: - if (succs == null || succs.length > 0) + if (succs.length != 0) throw new IllegalArgumentException ("throw or return with successor."); if (i != size - 1) throw new IllegalArgumentException ("return in the middle!"); - return; + needGoto = false; + break; case Opcodes.opc_ifeq: case Opcodes.opc_ifne: case Opcodes.opc_iflt: case Opcodes.opc_ifge: @@ -144,29 +205,38 @@ public final class Block { case Opcodes.opc_if_acmpeq: case Opcodes.opc_if_acmpne: case Opcodes.opc_ifnull: case Opcodes.opc_ifnonnull: case Opcodes.opc_jsr: - if (succs == null || succs.length != 2) + if (succs.length != 2) throw new IllegalArgumentException ("successors inappropriate for if/jsr"); + if (succs[0] == null && opcode == Opcodes.opc_jsr) + throw new IllegalArgumentException + ("null successors inappropriate for jsr"); if (i != size - 1) throw new IllegalArgumentException ("if/jsr in the middle!"); - return; + needGoto = false; } } - if (succs == null || succs.length != 1) + push = pop - depth; + if (needGoto && succs.length != 1) throw new IllegalArgumentException("no single successor block"); } + + public void getStackPopPush (int[] poppush) { + poppush[0] = pop; + poppush[1] = push; + return; + } /** * Set the code, i.e. instructions and successor blocks. * The instructions must be valid and match the successors. */ - public void setCode(Collection instrs, Block[] succs) { - this.instrs = (Instruction[]) - instrs.toArray(new Instruction[instrs.size()]); + public void setCode(Instruction[] instrs, Block[] succs) { + this.instrs = instrs; this.succs = succs; try { - checkConsistent(); + initCode(); } catch (IllegalArgumentException ex) { dumpCode(jode.GlobalOptions.err); throw ex; diff --git a/jode/jode/bytecode/ClassInfo.java b/jode/jode/bytecode/ClassInfo.java index 64f562e..91fdd54 100644 --- a/jode/jode/bytecode/ClassInfo.java +++ b/jode/jode/bytecode/ClassInfo.java @@ -228,6 +228,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable { private int status = 0; private boolean modified = false; + private boolean isGuessed = false; private ClassPath classpath; private int modifiers = -1; @@ -291,6 +292,14 @@ public final class ClassInfo extends BinaryInfo implements Comparable { * @see #load */ public static final int DECLARATIONS = 30; + /** + * This constant can be used as parameter to load. It specifies + * that everything in the class except debugging information and + * non-standard attributes should be loaded. + * + * @see #load + */ + public static final int NODEBUG = 80; /** * This constant can be used as parameter to load. It specifies * that everything in the class except non-standard attributes @@ -574,7 +583,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable { className = name.substring(dollar+1); outerClass = classpath.getClassInfo(declarer.getName()); /* As mentioned above OUTERCLASS is recursive */ - outerClass.loadFromReflection(declarer, OUTERCLASS); + if (outerClass.status < OUTERCLASS) + outerClass.loadFromReflection(declarer, OUTERCLASS); } else { /* Check if class name ends with $[numeric]$name or * $[numeric], in which case it is a method scoped @@ -610,7 +620,6 @@ public final class ClassInfo extends BinaryInfo implements Comparable { interfaces = new ClassInfo[ifaces.length]; for (int i=0; i= PUBLICDECLARATIONS) { Field[] fs; @@ -670,7 +679,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable { for (int i = is.length; --i >= 0; ) { innerClasses[i] = classpath.getClassInfo(is[i].getName()); /* As mentioned above OUTERCLASS is loaded recursive */ - innerClasses[i].loadFromReflection(is[i], OUTERCLASS); + if (innerClasses[i].status < OUTERCLASS) + innerClasses[i].loadFromReflection(is[i], OUTERCLASS); } } else innerClasses = null; @@ -1002,8 +1012,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable { throw new IllegalStateException(name); if (status >= howMuch) return; - if (classpath.loadClass(this, howMuch)) + if (classpath.loadClass(this, howMuch)) { + if (status < howMuch) + throw new IllegalStateException("state = "+status); return; + } throw new FileNotFoundException(name); } @@ -1025,16 +1038,18 @@ public final class ClassInfo extends BinaryInfo implements Comparable { */ public void guess(int howMuch) { - if (howMuch >= OUTERCLASS && status < OUTERCLASS) { + if (howMuch <= status) + throw new IllegalStateException("status = "+status); + isGuessed = true; + if (howMuch >= OUTERCLASS) { + modifiers = Modifier.PUBLIC | 0x20; int dollar = name.lastIndexOf('$'); if (dollar == -1) { /* normal class */ } else if (Character.isDigit(name.charAt(dollar+1))) { /* anonymous class */ - modifiers = Modifier.PUBLIC | 0x20; methodScoped = true; } else { - modifiers = Modifier.PUBLIC | 0x20; className = name.substring(dollar+1); int prevDollar = name.lastIndexOf('$', dollar); if (prevDollar >= 0 @@ -1045,22 +1060,24 @@ public final class ClassInfo extends BinaryInfo implements Comparable { outerClass = classpath.getClassInfo (name.substring(0, prevDollar)); } else { - /* inner class */ - modifiers = Modifier.PUBLIC | 0x20; + /* inner class, we assume it is static, so we don't + * get an exception when we search for the this$0 + * parameter in an constructor invocation. + */ + modifiers |= Modifier.STATIC; outerClass = classpath.getClassInfo (name.substring(0, dollar)); } } } - if (howMuch >= HIERARCHY && status < HIERARCHY) { - modifiers = Modifier.PUBLIC | 0x20; + if (howMuch >= HIERARCHY) { if (name.equals("java.lang.Object")) superclass = null; else superclass = classpath.getClassInfo("java.lang.Object"); interfaces = new ClassInfo[0]; } - if (howMuch >= PUBLICDECLARATIONS && status < PUBLICDECLARATIONS) { + if (howMuch >= PUBLICDECLARATIONS) { methods = new MethodInfo[0]; fields = new FieldInfo[0]; innerClasses = new ClassInfo[0]; @@ -1070,7 +1087,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable { /** * This is the counter part to load. It will drop all - * informations up keep and clean up the memory. + * informations bigger than "keep" and clean up the memory. * @param keep tells how much info we should keep, can be * NONE or anything that load accepts. * @see #load @@ -1080,7 +1097,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable { return; if (modified) { System.err.println("Dropping info between " + keep + " and " - + status + " in modified class" + this + "."); + + status + " in modified class " + this + "."); Thread.dumpStack(); return; } @@ -1101,23 +1118,21 @@ public final class ClassInfo extends BinaryInfo implements Comparable { methods = null; status = keep; } else { - if (keep < ALMOSTALL && status >= ALMOSTALL) { - for (int i=0; i < fields.length; i++) - fields[i].dropBody(); - for (int i=0; i < methods.length; i++) - methods[i].dropBody(); - } if (status >= DECLARATIONS) /* We don't drop non-public declarations, since this * is not worth it. */ keep = DECLARATIONS; + + for (int i=0; i < fields.length; i++) + fields[i].drop(keep); + for (int i=0; i < methods.length; i++) + methods[i].drop(keep); } - if (keep < ALMOSTALL && status >= ALMOSTALL) { + if (keep < ALMOSTALL) sourceFile = null; - super.dropAttributes(); - } + super.drop(keep); status = keep; } @@ -1129,6 +1144,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable { return name; } + public boolean isGuessed() { + return isGuessed; + } + /** * Returns the java class name of a class, without package or * outer classes. This is null for an anonymous class. For other diff --git a/jode/jode/bytecode/ClassPath.java b/jode/jode/bytecode/ClassPath.java index bf13df5..e6c1c6e 100644 --- a/jode/jode/bytecode/ClassPath.java +++ b/jode/jode/bytecode/ClassPath.java @@ -156,7 +156,7 @@ public class ClassPath { private class LocalPath extends Path { private File dir; - private LocalPath(File path) { + public LocalPath(File path) { dir = path; } @@ -253,7 +253,7 @@ public class ClassPath { } while (name.length() > 0); } - private ZipPath(ZipFile zipfile, String prefix) { + public ZipPath(ZipFile zipfile, String prefix) { this.file = zipfile; this.prefix = prefix; @@ -264,7 +264,7 @@ public class ClassPath { } } - private ZipPath(byte[] zipcontents, String prefix) + public ZipPath(byte[] zipcontents, String prefix) throws IOException { this.contents = zipcontents; @@ -354,9 +354,9 @@ public class ClassPath { } private class URLPath extends Path { - URL base; + private URL base; - private URLPath(URL base) { + public URLPath(URL base) { this.base = base; } diff --git a/jode/jode/bytecode/ConstantInstruction.java b/jode/jode/bytecode/ConstantInstruction.java index f91d456..16e319b 100644 --- a/jode/jode/bytecode/ConstantInstruction.java +++ b/jode/jode/bytecode/ConstantInstruction.java @@ -24,27 +24,17 @@ import jode.util.StringQuoter; * This class represents an instruction in the byte code. * */ -public class ConstantInstruction extends Instruction { +class ConstantInstruction extends Instruction { /** * The typesignature of the class/array. */ private Object constant; - /** - * Standard constructor: creates an opcode with parameter and - * lineNr. - */ - public ConstantInstruction(int opcode, Object constant, int lineNr) { - super(opcode, lineNr); - if (opcode != opc_ldc && opcode != opc_ldc2_w) - throw new IllegalArgumentException("Instruction has no typesig"); + ConstantInstruction(int opcode, Object constant) { + super(opcode); this.constant = constant; } - public ConstantInstruction(int opcode, Object constant) { - this(opcode, constant, -1); - } - public final Object getConstant() { return constant; @@ -61,4 +51,3 @@ public class ConstantInstruction extends Instruction { ? StringQuoter.quote((String) constant) : constant); } } - diff --git a/jode/jode/bytecode/FieldInfo.java b/jode/jode/bytecode/FieldInfo.java index e5568cf..6da18a9 100644 --- a/jode/jode/bytecode/FieldInfo.java +++ b/jode/jode/bytecode/FieldInfo.java @@ -44,10 +44,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable { this.modifier = modifier; } - protected void readAttribute(String name, int length, - ConstantPool cp, - DataInputStream input, - int howMuch) throws IOException { + void readAttribute(String name, int length, + ConstantPool cp, + DataInputStream input, + int howMuch) throws IOException { if (howMuch >= ClassInfo.DECLARATIONS && name.equals("ConstantValue")) { if (length != 2) @@ -68,19 +68,19 @@ public final class FieldInfo extends BinaryInfo implements Comparable { } else super.readAttribute(name, length, cp, input, howMuch); } - - public void read(ConstantPool constantPool, - DataInputStream input, int howMuch) throws IOException { + + void read(ConstantPool constantPool, + DataInputStream input, int howMuch) throws IOException { modifier = input.readUnsignedShort(); name = constantPool.getUTF8(input.readUnsignedShort()); typeSig = constantPool.getUTF8(input.readUnsignedShort()); readAttributes(constantPool, input, howMuch); } - public void reserveSmallConstants(GrowableConstantPool gcp) { + void reserveSmallConstants(GrowableConstantPool gcp) { } - public void prepareWriting(GrowableConstantPool gcp) { + void prepareWriting(GrowableConstantPool gcp) { gcp.putUTF8(name); gcp.putUTF8(typeSig); if (constant != null) { @@ -108,8 +108,8 @@ public final class FieldInfo extends BinaryInfo implements Comparable { return count; } - public void writeKnownAttributes(GrowableConstantPool gcp, - DataOutputStream output) + void writeKnownAttributes(GrowableConstantPool gcp, + DataOutputStream output) throws IOException { if (constant != null) { output.writeShort(gcp.putUTF8("ConstantValue")); @@ -132,7 +132,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable { } } - public void write(GrowableConstantPool constantPool, + void write(GrowableConstantPool constantPool, DataOutputStream output) throws IOException { output.writeShort(modifier); output.writeShort(constantPool.putUTF8(name)); @@ -140,8 +140,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable { writeAttributes(constantPool, output); } - public void dropBody() { - super.dropAttributes(); + void drop(int keep) { + if (keep < ClassInfo.DECLARATIONS) + constant = null; + super.drop(keep); } public String getName() { diff --git a/jode/jode/bytecode/Handler.java b/jode/jode/bytecode/Handler.java index 9fa38b1..5751e0d 100644 --- a/jode/jode/bytecode/Handler.java +++ b/jode/jode/bytecode/Handler.java @@ -1,4 +1,4 @@ -/* Handler Copyright (C) 1999 Jochen Hoenicke. +/* Handler Copyright (C) 2000 Jochen Hoenicke. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/jode/jode/bytecode/IncInstruction.java b/jode/jode/bytecode/IncInstruction.java index ceb8fe7..d51cd2b 100644 --- a/jode/jode/bytecode/IncInstruction.java +++ b/jode/jode/bytecode/IncInstruction.java @@ -23,28 +23,18 @@ package jode.bytecode; * This class represents an instruction in the byte code. * */ -public class IncInstruction extends SlotInstruction { +class IncInstruction extends SlotInstruction { /** * The amount of increment. */ private int increment; - /** - * Standard constructor: creates an opcode with parameter and - * lineNr. - */ - public IncInstruction(int opcode, int slot, int increment, int lineNr) { - super(opcode, slot, lineNr); - if (opcode != opc_iinc) - throw new IllegalArgumentException("Instruction has no increment"); - this.increment = increment; - } - /** * Creates a simple opcode, without any parameters. */ - public IncInstruction(int opcode, int slot, int increment) { - this(opcode, slot, increment, -1); + IncInstruction(int opcode, LocalVariableInfo lvi, int increment) { + super(opcode, lvi); + this.increment = increment; } /** diff --git a/jode/jode/bytecode/Instruction.java b/jode/jode/bytecode/Instruction.java index 501edbc..2adfb05 100644 --- a/jode/jode/bytecode/Instruction.java +++ b/jode/jode/bytecode/Instruction.java @@ -22,6 +22,20 @@ package jode.bytecode; /** * This class represents an instruction in the byte code. * + * We only allow a subset of opcodes. Other opcodes are mapped to + * their simpler version. When writing the bytecode the shortest + * possible bytecode is produced. + * + * The opcodes we map are: + *
+ * [iflda]load_x           -> [iflda]load
+ * [iflda]store_x          -> [iflda]store
+ * [ifa]const_xx, ldc_w    -> ldc
+ * [dl]const_xx            -> ldc2_w
+ * wide opcode             -> opcode
+ * tableswitch             -> lookupswitch
+ * [a]newarray             -> multianewarray
+ * 
*/ public class Instruction implements Opcodes{ /** @@ -32,80 +46,173 @@ public class Instruction implements Opcodes{ */ private int lineAndOpcode; + /** + * Creates a new simple Instruction with no parameters. We map + * some opcodes, so you must always use the mapped opcode. + * @param opcode the opcode of this instruction. + * @exception IllegalArgumentException if opcode is not in our subset + * or if opcode needs a parameter. */ + public static Instruction forOpcode(int opcode) { + switch (opcode) { + case opc_nop: + case opc_iaload: case opc_laload: case opc_faload: + case opc_daload: case opc_aaload: + case opc_baload: case opc_caload: case opc_saload: + case opc_iastore: case opc_lastore: case opc_fastore: + case opc_dastore: case opc_aastore: + case opc_bastore: case opc_castore: case opc_sastore: + case opc_pop: case opc_pop2: + case opc_dup: case opc_dup_x1: case opc_dup_x2: + case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: + case opc_swap: + case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: + case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: + case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: + case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: + case opc_irem: case opc_lrem: case opc_frem: case opc_drem: + case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: + case opc_ishl: case opc_lshl: + case opc_ishr: case opc_lshr: + case opc_iushr: case opc_lushr: + case opc_iand: case opc_land: + case opc_ior: case opc_lor: + case opc_ixor: case opc_lxor: + case opc_i2l: case opc_i2f: case opc_i2d: + case opc_l2i: case opc_l2f: case opc_l2d: + case opc_f2i: case opc_f2l: case opc_f2d: + case opc_d2i: case opc_d2l: case opc_d2f: + case opc_i2b: case opc_i2c: case opc_i2s: + case opc_lcmp: case opc_fcmpl: case opc_fcmpg: + case opc_dcmpl: case opc_dcmpg: + case opc_ireturn: case opc_lreturn: + case opc_freturn: case opc_dreturn: case opc_areturn: + case opc_return: + case opc_athrow: + case opc_arraylength: + case opc_monitorenter: case opc_monitorexit: + case opc_goto: + case opc_jsr: + case opc_ifeq: case opc_ifne: + case opc_iflt: case opc_ifge: + case opc_ifgt: case opc_ifle: + case opc_if_icmpeq: case opc_if_icmpne: + case opc_if_icmplt: case opc_if_icmpge: + case opc_if_icmpgt: case opc_if_icmple: + case opc_if_acmpeq: case opc_if_acmpne: + case opc_ifnull: case opc_ifnonnull: + return new Instruction(opcode); + default: + throw new IllegalArgumentException("Instruction has a parameter"); + } + } + + + /** + * Creates a new ldc Instruction. + * @param opcode the opcode of this instruction. + * @param constant the constant parameter. + * @exception IllegalArgumentException if opcode is not opc_ldc or + * opc_ldc2_w. + */ + public Instruction forOpcode(int opcode, Object constant) { + if (opcode == opc_ldc || opcode == opc_ldc2_w) + return new ConstantInstruction(opcode, constant); + throw new IllegalArgumentException("Instruction has no constant"); + } + + /** + * Creates a new Instruction with a local variable as parameter. + * @param opcode the opcode of this instruction. + * @param lvi the local variable parameter. + * @exception IllegalArgumentException if opcode is not in our subset + * or if opcode doesn't need a single local variable as parameter. + */ + public static Instruction forOpcode(int opcode, LocalVariableInfo lvi) { + if (opcode == opc_ret + || opcode >= opc_iload && opcode <= opc_aload + || opcode >= opc_istore && opcode <= opc_astore) + return new SlotInstruction(opcode, lvi); + throw new IllegalArgumentException("Instruction has no slot"); + } + + /** + * Creates a new Instruction with reference as parameter. + * @param opcode the opcode of this instruction. + * @param reference the reference parameter. + * @exception IllegalArgumentException if opcode is not in our subset + * or if opcode doesn't need a reference as parameter. + */ + public static Instruction forOpcode(int opcode, Reference reference) { + if (opcode >= opc_getstatic && opcode <= opc_invokeinterface) + return new ReferenceInstruction(opcode, reference); + throw new IllegalArgumentException("Instruction has no reference"); + } + + /** + * Creates a new Instruction with type signature as parameter. + * @param opcode the opcode of this instruction. + * @param typeSig the type signature parameter. + * @exception IllegalArgumentException if opcode is not in our subset + * or if opcode doesn't need a type signature as parameter. + */ + public static Instruction forOpcode(int opcode, String typeSig) { + switch (opcode) { + case opc_new: + case opc_checkcast: + case opc_instanceof: + return new TypeInstruction(opcode, typeSig); + default: + throw new IllegalArgumentException("Instruction has no type"); + } + } -// /** -// * Optional object data for this opcode. There are six different -// * usages of this field: -// *
-// *
opc_ldc / opc_ldc2_w
-// *
The constant of type Integer/Long/Float/Double/String.
-// *
opc_invokexxx / opc_xxxfield / opc_xxxstatic
-// *
The field/method Reference
-// *
opc_new / opc_checkcast / opc_instanceof
-// *
The typesignature of the class/array
-// *
opc_lookupswitch
-// *
The array of values of type int[]
-// *
opc_multianewarray
-// *
A DoubleParam: intValue contains dimension, objValue contains -// * reference
-// *
opc_[aildf]{load,store}
-// *
The LocalVariableInfo
-// *
opc_iinc
-// *
A DoubleParam: intValue contains count, objValue contains -// * local variable info.
-// *
-// */ -// private Object param; - -// /** -// * Create a new Instruction suitable for the given opcode. We map -// * some opcodes, so you must always use the mapped opcode. -// *
-//       * [iflda]load_x           -> [iflda]load
-//       * [iflda]store_x          -> [iflda]store
-//       * [ifa]const_xx, ldc_w    -> ldc
-//       * [dl]const_xx            -> ldc2_w
-//       * wide opcode             -> opcode
-//       * tableswitch             -> lookupswitch
-//       * [a]newarray             -> multianewarray
-//       * 
-// */ -// public static Instruction forOpcode(int opcode) { -// if (opcode == opc_iinc) -// return new IncInstruction(opcode); -// else if (opcode == opc_ret -// || opcode >= opc_iload && opcode <= opc_aload -// || opcode >= opc_istore && opcode <= opc_astore) -// return new SlotInstruction(opcode); -// else if (opcode >= opc_getstatic && opcode <= opc_invokeinterface) -// return new ReferenceInstruction(opcode); -// else switch (opcode) { -// case opc_new: -// case opc_checkcast: -// case opc_instanceof: -// return new TypeInstruction(opcode); -// case opc_multianewarray: -// return new TypeDimensionInstruction(opcode); -// default: -// return new Instruction(opcode); -// } -// } + /** + * Creates a new switch Instruction. + * @param opcode the opcode of this instruction must be opc_lookupswitch. + * @param values an array containing the different cases. + * @exception IllegalArgumentException if opcode is not opc_lookupswitch. + */ + public static Instruction forOpcode(int opcode, int[] values) { + if (opcode == opc_lookupswitch) + return new SwitchInstruction(opcode, values); + throw new IllegalArgumentException("Instruction has no values"); + } /** - * Standard constructor: creates an opcode with parameter and - * lineNr. + * Creates a new increment Instruction. + * @param opcode the opcode of this instruction. + * @param lvi the local variable parameter. + * @param increment the increment parameter. + * @exception IllegalArgumentException if opcode is not opc_iinc. */ - public Instruction(int opcode, int lineNr) { - if (stackDelta.charAt(opcode) == '\177') - throw new IllegalArgumentException("Unknown opcode: "+opcode); - this.lineAndOpcode = (lineNr << 8) | opcode; + public static Instruction forOpcode(int opcode, + LocalVariableInfo lvi, int increment) { + if (opcode == opc_iinc) + return new IncInstruction(opcode, lvi, increment); + throw new IllegalArgumentException("Instruction has no increment"); + } + + /** + * Creates a new Instruction with type signature and a dimension + * as parameter. + * @param opcode the opcode of this instruction. + * @param typeSig the type signature parameter. + * @param dimension the array dimension parameter. + * @exception IllegalArgumentException if opcode is not + * opc_multianewarray. + */ + public static Instruction forOpcode(int opcode, + String typeSig, int dimension) { + if (opcode == opc_multianewarray) + return new TypeDimensionInstruction(opcode, typeSig, dimension); + throw new IllegalArgumentException("Instruction has no dimension"); } /** * Creates a simple opcode, without any parameters. */ - public Instruction(int opcode) { - this(opcode, -1); + Instruction(int opcode) { + this.lineAndOpcode = (-1 << 8) | opcode; } /** @@ -263,6 +370,12 @@ public class Instruction implements Opcodes{ poppush[1] = delta >> 3; } + /** + * Gets a printable representation of the opcode with its + * parameters. This will not include the destination for jump + * instructions, since this information is not stored inside the + * instruction. + */ public final String getDescription() { return toString(); } @@ -276,6 +389,6 @@ public class Instruction implements Opcodes{ * \177 if opcode is illegal, or 8*stack_push + stack_pop otherwise * The string is created by scripts/createStackDelta.pl */ - protected final static String stackDelta = + final static String stackDelta = "\000\010\010\010\010\010\010\010\010\020\020\010\010\010\020\020\010\010\010\010\020\010\020\010\020\010\010\010\010\010\020\020\020\020\010\010\010\010\020\020\020\020\010\010\010\010\012\022\012\022\012\012\012\012\001\002\001\002\001\001\001\001\001\002\002\002\002\001\001\001\001\002\002\002\002\001\001\001\001\003\004\003\004\003\003\003\003\001\002\021\032\043\042\053\064\022\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\011\022\011\022\012\023\012\023\012\023\012\024\012\024\012\024\000\021\011\021\012\012\022\011\021\021\012\022\012\011\011\011\014\012\012\014\014\001\001\001\001\001\001\002\002\002\002\002\002\002\002\000\000\000\001\001\001\002\001\002\001\000\100\100\100\100\100\100\100\100\177\010\011\011\011\001\011\011\001\001\177\100\001\001\000\000"; } diff --git a/jode/jode/bytecode/MethodInfo.java b/jode/jode/bytecode/MethodInfo.java index 520049e..f4227e0 100644 --- a/jode/jode/bytecode/MethodInfo.java +++ b/jode/jode/bytecode/MethodInfo.java @@ -47,7 +47,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable { void readAttribute(String name, int length, ConstantPool cp, DataInputStream input, int howMuch) throws IOException { - if (howMuch >= ClassInfo.ALMOSTALL && name.equals("Code")) { + if (howMuch >= ClassInfo.NODEBUG && name.equals("Code")) { basicblocks = new BasicBlocks(this); basicblocks.read(cp, input, howMuch); } else if (howMuch >= ClassInfo.DECLARATIONS @@ -143,7 +143,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable { } } - public void write(GrowableConstantPool constantPool, + void write(GrowableConstantPool constantPool, DataOutputStream output) throws IOException { output.writeShort(modifier); output.writeShort(constantPool.putUTF8(name)); @@ -151,9 +151,14 @@ public final class MethodInfo extends BinaryInfo implements Comparable { writeAttributes(constantPool, output); } - public void dropBody() { - basicblocks = null; - super.dropAttributes(); + void drop(int keep) { + if (keep < ClassInfo.DECLARATIONS) + exceptions = null; + if (keep < ClassInfo.NODEBUG) + basicblocks = null; + else + basicblocks.drop(keep); + super.drop(keep); } public String getName() { diff --git a/jode/jode/bytecode/ReferenceInstruction.java b/jode/jode/bytecode/ReferenceInstruction.java index cc1ec71..271d198 100644 --- a/jode/jode/bytecode/ReferenceInstruction.java +++ b/jode/jode/bytecode/ReferenceInstruction.java @@ -23,26 +23,12 @@ package jode.bytecode; * This class represents an instruction that needs a reference, i.e. * a method invocation or field access instruction. */ -public final class ReferenceInstruction extends Instruction { +class ReferenceInstruction extends Instruction { private Reference reference; - /** - * Standard constructor: creates an opcode with parameter and - * lineNr. - */ - public ReferenceInstruction(int opcode, Reference reference, int lineNr) - { - super(opcode, lineNr); - if (opcode < opc_getstatic || opcode > opc_invokeinterface) - throw new IllegalArgumentException("Instruction has no reference"); - this.reference = reference; - } - - /** - * Creates a simple opcode, without any parameters. - */ public ReferenceInstruction(int opcode, Reference ref) { - this(opcode, ref, -1); + super(opcode); + this.reference = ref; } public final Reference getReference() @@ -67,8 +53,7 @@ public final class ReferenceInstruction extends Instruction { /*{ require { poppush != null && poppush.length == 2 :: "poppush must be an array of two ints" } } */ { - Reference ref = getReference(); - String typeSig = ref.getType(); + String typeSig = reference.getType(); int opcode = getOpcode(); switch (opcode) { case opc_invokevirtual: diff --git a/jode/jode/bytecode/SlotInstruction.java b/jode/jode/bytecode/SlotInstruction.java index b232837..02246e9 100644 --- a/jode/jode/bytecode/SlotInstruction.java +++ b/jode/jode/bytecode/SlotInstruction.java @@ -23,36 +23,14 @@ package jode.bytecode; * This class represents an instruction in the byte code. * */ -public class SlotInstruction extends Instruction { +class SlotInstruction extends Instruction { private LocalVariableInfo lvi; - /** - */ - public SlotInstruction(int opcode, LocalVariableInfo lvi, int lineNr) { - super(opcode, lineNr); - if (opcode != opc_iinc && opcode != opc_ret - && (opcode < opc_iload || opcode > opc_aload) - && (opcode < opc_istore || opcode > opc_astore)) - throw new IllegalArgumentException("Instruction has no slot"); - this.lvi = lvi; - } - - /** - */ - public SlotInstruction(int opcode, int slot, int lineNr) { - this(opcode, LocalVariableInfo.getInfo(slot), lineNr); - } - /** */ public SlotInstruction(int opcode, LocalVariableInfo lvi) { - this(opcode, lvi, -1); - } - - /** - */ - public SlotInstruction(int opcode, int slot) { - this(opcode, LocalVariableInfo.getInfo(slot), -1); + super(opcode); + this.lvi = lvi; } public boolean isStore() { diff --git a/jode/jode/bytecode/SwitchInstruction.java b/jode/jode/bytecode/SwitchInstruction.java index b37440f..8e22e0a 100644 --- a/jode/jode/bytecode/SwitchInstruction.java +++ b/jode/jode/bytecode/SwitchInstruction.java @@ -24,7 +24,7 @@ import jode.util.StringQuoter; * This class represents an instruction in the byte code. * */ -public class SwitchInstruction extends Instruction { +class SwitchInstruction extends Instruction { /** * The values for this switch. */ @@ -34,20 +34,11 @@ public class SwitchInstruction extends Instruction { * Standard constructor: creates an opcode with parameter and * lineNr. */ - public SwitchInstruction(int opcode, int[] values, int lineNr) { - super(opcode, lineNr); - if (opcode != opc_lookupswitch) - throw new IllegalArgumentException("Instruction is no switch"); + SwitchInstruction(int opcode, int[] values) { + super(opcode); this.values = values; } - /** - * Creates a simple opcode, without any parameters. - */ - public SwitchInstruction(int opcode, int[] values) { - this(opcode, values, -1); - } - public final int[] getValues() { return values; diff --git a/jode/jode/bytecode/TypeDimensionInstruction.java b/jode/jode/bytecode/TypeDimensionInstruction.java index b077f3b..4281481 100644 --- a/jode/jode/bytecode/TypeDimensionInstruction.java +++ b/jode/jode/bytecode/TypeDimensionInstruction.java @@ -20,32 +20,18 @@ package jode.bytecode; /** - * This class represents an instruction in the byte code. + * This class represents an opc_multianewarray instruction. * */ -public class TypeDimensionInstruction extends TypeInstruction { +class TypeDimensionInstruction extends TypeInstruction { /** * The dimension of this multianewarray operation. */ private int dimension; - /** - * Standard constructor: creates an opcode with parameter and - * lineNr. - */ - public TypeDimensionInstruction(int opcode, String type, int dimension, - int lineNr) { - super(opcode, type, lineNr); - if (opcode != opc_multianewarray) - throw new IllegalArgumentException("Instruction has no dimension"); - this.dimension = dimension; - } - - /** - * Creates a simple opcode, without any parameters. - */ public TypeDimensionInstruction(int opcode, String type, int dimension) { - this(opcode, type, dimension, -1); + super(opcode, type); + this.dimension = dimension; } /** diff --git a/jode/jode/bytecode/TypeInstruction.java b/jode/jode/bytecode/TypeInstruction.java index abce932..37719e7 100644 --- a/jode/jode/bytecode/TypeInstruction.java +++ b/jode/jode/bytecode/TypeInstruction.java @@ -23,29 +23,15 @@ package jode.bytecode; * This class represents an instruction in the byte code. * */ -public class TypeInstruction extends Instruction { +class TypeInstruction extends Instruction { /** * The typesignature of the class/array. */ private String typeSig; - /** - * Standard constructor: creates an opcode with parameter and - * lineNr. - */ - public TypeInstruction(int opcode, String typeSig, int lineNr) { - super(opcode, lineNr); - if (opcode != opc_new && opcode != opc_checkcast - && opcode != opc_instanceof && opcode != opc_multianewarray) - throw new IllegalArgumentException("Instruction has no typesig"); - this.typeSig = typeSig; - } - - /** - * Creates a simple opcode, without any parameters. - */ public TypeInstruction(int opcode, String typeSig) { - this(opcode, typeSig, -1); + super(opcode); + this.typeSig = typeSig; } public final String getClazzType() diff --git a/jode/jode/bytecode/package.html b/jode/jode/bytecode/package.html index 1ae5b55..64409b9 100644 --- a/jode/jode/bytecode/package.html +++ b/jode/jode/bytecode/package.html @@ -68,7 +68,7 @@ You can also use this package to create and write new classes: ... ClassPath path = new ClassPath("/usr/lib/java/lib/classes.zip"); ClassInfo clazz = path.getClassInfo("my.new.Class"); - clazz.setModifiers(Modifiers.PUBLIC); + clazz.setModifiers(Modifier.PUBLIC); clazz.setSourceFile("Class.pl"); clazz.set... clazz.write(zipOutputStream);